*/
static int rt_test( ) {
uta_ctx_t* ctx; // context needed to test load static rt
+ uta_ctx_t* pctx; // "private" context for route manager communication tests
route_table_t* rt; // route table
route_table_t* crt; // cloned route table
rtable_ent_t* rte; // route table entries from table
rtable_ent_t* rte2;
endpoint_t* ep; // endpoint added
+ endpoint_t* ep2;
int more = 0; // more flag from round robin
int errors = 0; // number errors found
int i;
int enu = 0;
int state;
char *buf;
+ char *buf2;
char* seed_fname; // seed file
- nng_socket nn_sock; // this is a struct in nng, so difficult to validate
+ SOCKET_TYPE nn_sock; // differnt in each transport (nng == struct, SI/Nano == int)
rmr_mbuf_t* mbuf; // message for meid route testing
+ void* p; // generic pointer
+
+ #ifndef NNG_UNDER_TEST
+ si_ctx_t* si_ctx = NULL;
+ #endif
setenv( "ENV_VERBOSE_FILE", ".ut_rmr_verbose", 1 ); // allow for verbose code in rtc to be driven
i = open( ".ut_rmr_verbose", O_RDWR | O_CREAT, 0644 );
close( i );
}
-
+
/*
The hacky code below calls the necessary rmr functions to create a route table
as though the following were read and parsed by the rmr functions. (This tests
the individual funcitons and avoids writing another parser, so it's not pretty.)
-
+
mse | 0 | 0 | yahoo.com:4561,localhost:4562
mse | 1 | 0 | localhost:4560,localhost:4568,localhost:4569; localhost:4561,localhost:4562
mse | 2 | 0 | localhost:4563,localhost:4564
entries[enu].group = 0; entries[enu].ep_name = "localhost:5512"; enu++;
- rt = uta_rt_init( ); // get us a route table
+ rt = uta_rt_init( NULL );
+ errors += fail_if_false( rt == NULL, "rt_init given a nil context didn't return nil" );
+
+ ctx = mk_dummy_ctx(); // make a dummy with rtgate mutex
+ rt = uta_rt_init( ctx ); // get us a route table
if( (errors += fail_if_nil( rt, "pointer to route table" )) ) {
fprintf( stderr, "<FAIL> abort: cannot continue without a route table\n" );
exit( 1 );
// ----- end hacking together a route table ---------------------------------------------------
- crt = uta_rt_clone( rt ); // clone only the endpoint entries
+ crt = uta_rt_clone( ctx, rt, NULL, 0 ); // create a new rt and clone only the me entries
errors += fail_if_nil( crt, "cloned route table" );
if( crt ) {
c1 = count_entries( rt, 1 );
c2 = count_entries( crt, 1 );
errors += fail_not_equal( c1, c2, "cloned (endpoints) table entries space 1 count (b) did not match original table count (a)" );
-
+
c2 = count_entries( crt, 0 );
errors += fail_not_equal( c2, 0, "cloned (endpoints) table entries space 0 count (a) was not zero as expected" );
+
+ errors += fail_if_false( crt->ephash == rt->ephash, "ephash pointer in cloned table is not right" );
uta_rt_drop( crt );
}
- crt = uta_rt_clone_all( rt ); // clone all entries
- errors += fail_if_nil( crt, "cloned all route table" );
+ crt = uta_rt_clone( ctx, rt, NULL, 1 ); // clone all entries (MT and ME)
+ errors += fail_if_nil( crt, "cloned (all) route table" );
if( crt ) {
c1 = count_entries( rt, 0 );
c2 = count_entries( crt, 0 );
errors += fail_not_equal( c1, c2, "cloned (all) table entries space 0 count (b) did not match original table count (a)" );
-
+
c1 = count_entries( rt, 1 );
c2 = count_entries( crt, 1 );
errors += fail_not_equal( c1, c2, "cloned (all) table entries space 1 count (b) did not match original table count (a)" );
+
+ errors += fail_if_false( crt->ephash == rt->ephash, "ephash pointer in cloned table (all) is not right" );
uta_rt_drop( crt );
}
-
+
+ #ifdef NNG_UNDER_TEST
+ if( (ctx = (uta_ctx_t *) malloc( sizeof( uta_ctx_t ) )) != NULL ) { // get a "context" needed for si testing
+ memset( ctx, 0, sizeof( *ctx ) );
+ ctx->rtable = rt;
+ } else {
+ fprintf( stderr, "<FAIL> cannot acllocate a context, cannot continue rtable tests\n" );
+ return errors;
+ }
+ #else
+ ctx = mk_dummy_ctx();
+ #endif
+
+ ctx->rtable = rt;
ep = uta_get_ep( rt, "localhost:4561" );
errors += fail_if_nil( ep, "end point (fetch by name)" );
errors += fail_not_nil( ep, "end point (fetch by name with bad name)" );
ep = NULL;
- state = uta_epsock_byname( rt, "localhost:4561", &nn_sock, &ep ); // this should be found
+ #ifdef NNG_UNDER_TEST
+ state = uta_epsock_byname( rt, "localhost:4561", &nn_sock, &ep ); // this should be found
+ #else
+ state = uta_epsock_byname( ctx, "localhost:4561", &nn_sock, &ep ); // this should be found
+ #endif
errors += fail_if_equal( state, 0, "socket (by name)" );
errors += fail_if_nil( ep, "epsock_byname did not populate endpoint pointer when expected to" );
//alt_value = uta_epsock_byname( rt, "localhost:4562" ); // we might do a memcmp on the two structs, but for now nothing
//errors += fail_if_equal( value, alt_value, "app1/app2 sockets" );
+ #if NNG_UNDER_TEST
+ state = uta_epsock_byname( NULL, "localhost:4561", &nn_sock, &ep ); // test coverage on nil checks
+ #else
+ state = uta_epsock_byname( NULL, "localhost:4561", &nn_sock, &ep );
+ errors += fail_not_equal( state, 0, "socket (by name) nil context check returned true" );
+
+ p = ctx->si_ctx;
+ ctx->si_ctx = NULL; // set to drive second test
+ state = uta_epsock_byname( ctx, "localhost:4561", &nn_sock, &ep );
+ ctx->si_ctx = p;
+ #endif
+ errors += fail_not_equal( state, 0, "socket (by name) nil check returned true" );
+
+ if( ep ) { // if previous test fails, cant run this
+ ep->open = 1;
+ #if NNG_UNDER_TEST
+ state = uta_epsock_byname( rt, "localhost:4561", &nn_sock, NULL ); // test coverage on nil checks
+ #else
+ state = uta_epsock_byname( ctx, "localhost:4561", &nn_sock, NULL );
+ #endif
+ errors += fail_if_equal( state, 0, "socket (by name) open ep check returned false" );
+ }
+
// --- test that the get_rte function finds expected keys, and retries to find 'bad' sid attempts for valid mtypes with no sid
rte = uta_get_rte( rt, 0, 1, TRUE ); // s=0 m=1 is defined, so this should return a pointer
rte = uta_get_rte( rt, 12, 3, FALSE ); // this combo does not exist and should fail when alt-key is not allowed (false)
errors += fail_not_nil( rte, "get_rte returned a pointer for s=12, m=3, false" );
- rte = uta_get_rte( rt, 12, 3, TRUE ); // this should return the entry for the 3/-1 combination
+ rte = uta_get_rte( rt, 12, 3, TRUE ); // this should return the entry for the 3/-1 combination
errors += fail_if_nil( rte, "get_rte did not return a pointer for s=12, m=3, true" );
+
alt_value = -1;
rte = uta_get_rte( rt, 0, 1, FALSE ); // get an rte for the next loop
if( rte ) {
for( i = 0; i < 10; i++ ) { // round robin return value should be different each time
- value = uta_epsock_rr( rte, 0, &more, &nn_sock, &ep ); // msg type 1, group 1
+ #ifdef NNG_UNDER_TEST
+ value = uta_epsock_rr( rte, 0, &more, &nn_sock, &ep ); // msg type 1, group 1
+ #else
+ value = uta_epsock_rr( ctx, rte, 0, &more, &nn_sock, &ep );
+ #endif
+
errors += fail_if_equal( value, alt_value, "round robiin sockets with multiple end points" );
errors += fail_if_false( more, "more for mtype==1" );
alt_value = value;
rte = uta_get_rte( rt, 0, 3, FALSE ); // get an rte for the next loop
if( rte ) {
for( i = 0; i < 10; i++ ) { // this mtype has only one endpoint, so rr should be same each time
- value = uta_epsock_rr( rte, 0, NULL, &nn_sock, &ep ); // also test ability to deal properly with nil more pointer
+ #ifdef NNG_UNDER_TEST
+ value = uta_epsock_rr( rte, 0, NULL, &nn_sock, &ep ); // also test ability to deal properly with nil more pointer
+ #else
+ value = uta_epsock_rr( ctx, rte, 0, NULL, &nn_sock, &ep );
+ #endif
+
if( i ) {
errors += fail_not_equal( value, alt_value, "round robin sockets with one endpoint" );
errors += fail_not_equal( more, -1, "more value changed in single group instance" );
}
rte = uta_get_rte( rt, 11, 3, TRUE );
- state = uta_epsock_rr( rte, 22, NULL, NULL, &ep );
+ #ifdef NNG_UNDER_TEST
+ state = uta_epsock_rr( rte, 22, NULL, NULL, &ep );
+ #else
+ state = uta_epsock_rr( ctx, rte, 22, NULL, NULL, &ep );
+ #endif
errors += fail_if_true( state, "uta_epsock_rr returned bad (non-zero) state when given nil socket pointer" );
- uta_rt_clone( NULL ); // verify null parms don't crash things
+ uta_rt_clone( ctx, NULL, NULL, 0 ); // verify null parms don't crash things
uta_rt_drop( NULL );
- uta_epsock_rr( NULL, 0, &more, &nn_sock, &ep ); // drive null case for coverage
+ #ifdef NNG_UNDER_TEST
+ uta_epsock_rr( NULL, 0, &more, &nn_sock, &ep ); // drive null case for coverage
+ state = uta_epsock_rr( rte, 22, NULL, NULL, &ep );
+ #else
+ state = uta_epsock_rr( NULL, NULL, 0, &more, &nn_sock, &ep ); // drive null case for coverage
+ errors += fail_not_equal( state, 0, "uta_epsock_rr did not return false when given nil ctx" );
+
+ state = uta_epsock_rr( ctx, NULL, 0, &more, &nn_sock, &ep );
+ errors += fail_not_equal( state, 0, "uta_epsock_rr did not return false when given nil rte" );
+
+ state = uta_epsock_rr( ctx, rte, 10000, &more, &nn_sock, &ep );
+ errors += fail_not_equal( state, 0, "uta_epsock_rr did not return false when given invalid group number" );
+ #endif
uta_add_rte( NULL, 99, 1 );
uta_get_rte( NULL, 0, 1000, TRUE );
free( buf );
}
+ fprintf( stderr, "<INFO> test is overtly dropping rt table at %p\n", rt );
+ ctx->rtable = NULL;
uta_rt_drop( rt );
rt = NULL;
- if( (ctx = (uta_ctx_t *) malloc( sizeof( uta_ctx_t ) )) != NULL ) {
- memset( ctx, 0, sizeof( *ctx ) );
-
- if( (seed_fname = getenv( "RMR_SEED_RT" )) != NULL ) {
- read_static_rt( ctx, 0 );
- rt = ctx->rtable;
- errors += fail_if_nil( rt, "read seed table didn't generate a rtable pointer in context" );
- unsetenv( "RMR_SEED_RT" ); // remove for next test
- }
+ // --- force the load of a RT which has some edge case forcing issues
+ if( ctx ) {
+ char* rt_stuff =
+ "newrt | start | dummy-seed\n"
+ "mse | 1 | -1 | localhost:84306\n"
+ "mse | 10 | -1 | localhost:84306\n"
+ "mse | 10 | 1 | localhost:84306\n"
+ "# should cause failure because there aren't 10 entries above\n"
+ "newrt | end | 10\n"
+
+ "# this table has no end\n"
+ "newrt | start | dummy-seed\n"
+ "mse | 1 | -1 | localhost:84306\n"
+ "mse | 10 | -1 | localhost:84306\n"
+ "mse | 10 | 1 | localhost:84306\n"
+
+ "# this table should be ok\n"
+ "newrt | start | dummy-seed\n"
+ "mse | 1 | -1 | localhost:84306\n"
+ "mse | 10 | -1 | localhost:84306\n"
+ "mse | 10 | 1 | localhost:84306\n"
+ "newrt | end | 3\n"
+
+ "# for an update to the existing table\n"
+ "# not in progress; drive that exception check\n"
+ "update | end | 23\n"
+
+ "update | start | dummy-seed\n"
+ "mse | 3 | 2 | localhost:2222\n"
+ "# short record to drive test\n"
+ "del\n"
+ "# no table end for exception handling\n"
+
+ "update | start | dummy-seed\n"
+ "mse | 2 | 2 | localhost:2222\n"
+ "del | 10 | 1\n"
+ "update | end | 2\n";
+
+ fprintf( stderr, "<INFO> loading RT from edge case static table\n" );
+ fprintf( stderr, "<INFO> %s\n", rt_stuff );
+ gen_custom_rt( ctx, rt_stuff );
+ fprintf( stderr, "<INFO> edge case load completed\n" );
+ errors += fail_if_nil( ctx->rtable, "edge case route table didn't generate a pointer into the context" );
+
+ unsetenv( "RMR_SEED_RT" ); // remove for next read try
read_static_rt( ctx, 0 ); // drive for not there coverage
}
ep = (endpoint_t *) malloc( sizeof( *ep ) );
+ memset( ep, 0, sizeof( ep ) );
pthread_mutex_init( &ep->gate, NULL );
ep->name = strdup( "worm" );
ep->addr = NULL;
- state = uta_link2( ep );
- errors += fail_if_true( state, "link2 did not return false when given nil pointers" );
+ ep->notify = 1;
+ #ifdef NNG_UNDER_TEST
+ state = uta_link2( ep );
+ #else
+ state = uta_link2( ctx, ep );
+ #endif
+ errors += fail_if_true( state, "link2 did not return false when given a bad target name" );
+
+ #ifdef NNG_UNDER_TEST
+ state = uta_link2( NULL );
+ #else
+ state = uta_link2( ctx, NULL );
+ errors += fail_if_true( state, "link2 did not return false when given nil ep pointer" );
+
+ state = uta_link2( NULL, ep );
+ #endif
+ errors += fail_if_true( state, "link2 did not return false when given nil pointer" );
+
+ ep->name = strdup( "localhost:5512" );
+ ep->open = 1;
+ #ifdef NNG_UNDER_TEST
+ state = uta_link2( ep ); // drive for coverage
+ #else
+ state = uta_link2( ctx, ep );
+ #endif
+ errors += fail_if_false( state, "link2 did returned false when given open ep" );
+
+ #ifndef NNG_UNDER_TEST
+ ep->open = 0; // context is used only if ep not open, so to check this test close the ep
+ ep->notify = 1;
+ state = rt_link2_ep( NULL, ep );
+ errors += fail_if_true( state, "rt_link2_ep returned true when given bad context" );
+
+ state = rt_link2_ep( ctx, NULL );
+ errors += fail_if_true( state, "rt_link2_ep returned true when given bad ep" );
+
+ ep->open = 1;
+ state = rt_link2_ep( ctx, ep );
+ errors += fail_if_false( state, "rt_link2_ep returned false when given an open ep" );
+
+ ep->open = 0;
+ state = rt_link2_ep( ctx, ep );
+ errors += fail_if_false( state, "rt_link2_ep returned false when given a closed ep" );
+
+ ep->open = 1;
+ uta_ep_failed( ep );
+ errors += fail_if_true( ep->open, "uta_ep_failed didn't set open flag to false" );
+
+ #endif
+
// ----------------- test the meid support for looking up an endpoint based on the meid in the message -----
+ ctx->rtable = NULL;
ctx->my_name = strdup( "my_host_name" ); // set up to load a rtable
ctx->my_ip = strdup( "192.168.1.30" );
gen_rt( ctx ); // generate a route table with meid entries and hang off ctx
mbuf->len = 100;
rmr_str2meid( mbuf, "meid1" ); // id that we know is in the map
- state = epsock_meid( ctx->rtable, mbuf, &nn_sock, &ep );
- errors += fail_if_nil( ep, "ep was nil when looking up ep with known meid in message" );
- errors += fail_not_equal( state, 1, "state was not true when looking up ep with known meid in message" );
+ #ifdef NNG_UNDER_TEST
+ ep = NULL; // force to nil so we see it go non-nil
+ state = epsock_meid( ctx->rtable, mbuf, &nn_sock, &ep );
+ errors += fail_if_nil( ep, "ep was nil when looking up ep with known meid in message" );
+ errors += fail_not_equal( state, 1, "state was not true when looking up ep with known meid in message" );
+
+ rmr_str2meid( mbuf, "XXXmeid1" ); // id that we know is NOT in the map
+ state = epsock_meid( ctx->rtable, mbuf, &nn_sock, &ep );
+ // it is NOT a valid check to test ep for nil -- epsock_mied doesn't guarentee ep is set/cleared when state is false
+ errors += fail_not_equal( state, 0, "state was not false when looking up ep with unknown meid in message" );
+ #else
+ ep = NULL; // force to nil so we see it go non-nil
+ state = epsock_meid( ctx, ctx->rtable, mbuf, &nn_sock, &ep );
+ errors += fail_if_nil( ep, "ep was nil when looking up ep with known meid in message" );
+ errors += fail_not_equal( state, 1, "state was not true when looking up ep with known meid in message" );
+
+ state = epsock_meid( ctx, ctx->rtable, mbuf, &nn_sock, &ep ); // a second call to drive open == true check for coverage
+ errors += fail_if_nil( ep, "ep was nil when looking up ep with known meid in message; on open ep" );
+ errors += fail_not_equal( state, 1, "state was not true when looking up ep with known meid in message; on open ep" );
+
+ rmr_str2meid( mbuf, "XXXmeid1" ); // id that we know is NOT in the map
+ state = epsock_meid( ctx, ctx->rtable, mbuf, &nn_sock, &ep );
+ // it is NOT a valid check to test ep for nil -- epsock_mied doesn't guarentee ep is set/cleared when state is false
+ errors += fail_not_equal( state, 0, "state was not false when looking up ep with unknown meid in message" );
+
+ state = epsock_meid( NULL, ctx->rtable, mbuf, &nn_sock, &ep );
+ errors += fail_not_equal( state, 0, "epsock_meid returned true when given nil context" );
+
+ state = epsock_meid( ctx, ctx->rtable, mbuf, NULL, &ep );
+ errors += fail_not_equal( state, 0, "epsock_meid returned true when given nil socket pointer" );
+ #endif
+
+ // ------------ debugging and such; coverage only calls ----------------------------------------------------------
+ ep_stats( ctx->rtable, NULL, "name", NULL, NULL ); // ensure no crash when given nil pointer
+ rt_epcounts( ctx->rtable, "testing" );
+ rt_epcounts( NULL, "testing" );
+
+ buf = ensure_nlterm( NULL );
+ errors += fail_if_nil( buf, "ensure nlterm returned null pointer when given nil ptr" );
+ if( buf ) {
+ errors += fail_not_equal( strlen( buf ), 1, "ensure nlterm returned incorrect length string when given nil pointer" );
+ free( buf );
+ }
+
+ buf = ensure_nlterm( strdup( "x" ) ); // should return "x\n"
+ errors += fail_if_nil( buf, "ensure nlterm returned null pointer when given single char string" );
+ if( buf ) {
+ errors += fail_not_equal( strlen( buf ), 2, "ensure nlterm returned incorrect length string when given single char string" );
+ free( buf );
+ }
+
+ buf = strdup( "x\n" );
+ buf2 = ensure_nlterm( buf ); // buffer returned should be the same
+ if( fail_not_pequal( buf, buf2, "ensure nlterm returned new buffer for one char string with newline" ) ) {
+ errors++;
+ free( buf2 );
+ }
+ free( buf );
+
+ buf = strdup( "Missing our trips to Gloria's for papossas.\n" );
+ buf2 = ensure_nlterm( buf ); // buffer returned should be the same
+ if( fail_not_pequal( buf, buf2, "ensure nlterm returned new buffer for string with newline" ) ) {
+ errors++;
+ free( buf2 );
+ }
+ free( buf );
+
+ buf = ensure_nlterm( strdup( "Stand up and cheer!" ) ); // force addition of newline
+ if( buf ) {
+ errors += fail_not_equal( strcmp( buf, "Stand up and cheer!\n" ), 0, "ensure nlterm didn't add newline" );
+ free( buf );
+ buf = NULL;
+ }
+
+
+ // ------------- route manager request/response funcitons -------------------------------------------------------
+ {
+ rmr_mbuf_t* smsg;
+
+ smsg = rmr_alloc_msg( ctx, 1024 );
+ send_rt_ack( ctx, smsg, "123456", 0, "no reason" );
+
+ pctx = mk_dummy_ctx();
+ ctx->rtg_whid = -1;
+ state = send_update_req( pctx, ctx );
+ errors += fail_not_equal( state, 0, "send_update_req did not return 0" );
+
+ ctx->rtg_whid = rmr_wh_open( ctx, "localhost:19289" );
+ state = send_update_req( pctx, ctx );
+ errors += fail_if_equal( state, 0, "send_update_req to an open whid did not return 0" );
+ }
+
+
+ // ------------- si only; fd to ep conversion functions ---------------------------------------------------------
+ #ifndef NNG_UNDER_TEST
+ ep2 = (endpoint_t *) malloc( sizeof( *ep ) );
+
+ fd2ep_init( ctx );
+ fd2ep_add( ctx, 10, ep2 );
+
+ ep = fd2ep_get( ctx, 10 );
+ errors += fail_if_nil( ep, "fd2ep did not return pointer for known mapping" );
+ errors += fail_if_false( ep == ep2, "fd2ep did not return same pointer that was added" );
+
+ ep = fd2ep_get( ctx, 20 );
+ errors += fail_not_nil( ep, "fd2ep did returned a pointer for unknown mapping" );
+
+ ep = fd2ep_del( ctx, 10 );
+ errors += fail_if_nil( ep, "fd2ep delete did not return pointer for known mapping" );
+ errors += fail_if_false( ep == ep2, "fd2ep delete did not return same pointer that was added" );
+
+ ep = fd2ep_del( ctx, 20 );
+ errors += fail_not_nil( ep, "fd2ep delete returned a pointer for unknown mapping" );
+ #endif
- rmr_str2meid( mbuf, "XXXmeid1" ); // id that we know is NOT in the map
- state = epsock_meid( ctx->rtable, mbuf, &nn_sock, &ep );
- errors += fail_not_nil( ep, "ep was NOT nil when looking ep up with unknown meid in message" );
- errors += fail_not_equal( state, 0, "state was not false when looking up ep with unknown meid in message" );
+ // ---------------- misc coverage tests --------------------------------------------------------------------------
+ collect_things( NULL, NULL, NULL, NULL, NULL ); // these both return null, these test NP checks
+ collect_things( NULL, NULL, NULL, NULL, (void *) 1234 ); // the last is an invalid pointer, but check needed to force check on previous param
+ del_rte( NULL, NULL, NULL, NULL, NULL );
return !!errors; // 1 or 0 regardless of count
}