Address potential error state after good send
This change addresses the potential to "hide" the good
status of a send in the case where there are multiple
round-robin groups for a message type. The send algorithm
was modified to eliminate the potential edge case and
to report a successful result if the message was accepted
for delivery to at least one group.
Two issues identified by valgrind (use of a potentially
uninitialised variable in a jump) were also corrected.
Intermediate commits:
Signed-off-by: E. Scott Daniels <daniels@research.att.com>
Add error tag to msg
Missing ERR on failure message.
Signed-off-by: E. Scott Daniels <daniels@research.att.com>
Prevent NPE in symtab
Signed-off-by: E. Scott Daniels <daniels@research.att.com>
Adjust unit tests, fix valgrind inddicated issues
Unit tests were added to verify the new get rte function.
Valgrind indicated several places where a conditional was
using a potentially uninitialised variable; these were fixed.
Signed-off-by: E. Scott Daniels <daniels@research.att.com>
Change-Id: I7c0a49713ab3d6fbb8f66e3d286049762433dc58
diff --git a/test/rt_static_test.c b/test/rt_static_test.c
index 13a216b..6d416ef 100644
--- a/test/rt_static_test.c
+++ b/test/rt_static_test.c
@@ -79,6 +79,19 @@
}
/*
+ Builds a route table key.
+*/
+static uint64_t build_key( uint32_t mtype, uint32_t sid ) {
+ uint64_t k;
+
+ k = (uint64_t) sid << 32;
+ k += mtype;
+
+fprintf( stderr, "<INFO> build key: %x %x --> %llx\n", (int) mtype, (int) sid, (long long) k );
+ return k;
+}
+
+/*
This is the main route table test. It sets up a very specific table
for testing (not via the generic setup function for other test
situations).
@@ -87,7 +100,8 @@
uta_ctx_t* ctx; // context needed to test load static rt
route_table_t* rt; // route table
route_table_t* crt; // cloned route table
- rtable_ent_t* rte; // entry in the table
+ rtable_ent_t* rte; // route table entries from table
+ rtable_ent_t* rte2;
endpoint_t* ep; // endpoint added
int more = 0; // more flag from round robin
int errors = 0; // number errors found
@@ -99,9 +113,9 @@
int value;
int alt_value;
ei_t entries[50]; // end point information
- int gcounts[5]; // number of groups in this set
- int ecounts[5]; // number of elements per group
- int mtypes[5]; // msg type for each group set
+ int gcounts[7]; // number of groups in this set
+ int ecounts[7]; // number of elements per group
+ uint64_t mtypes[7]; // mtype/sid 'key' in the modern RMR world
char* tok;
char* nxt_tok;
int enu = 0;
@@ -113,40 +127,62 @@
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 );
if( i >= 0 ) {
- write( 1, "2\n", 2 );
+ write( i, "2\n", 2 );
close( i );
}
- gcounts[0] = 1; // build entry info -- this is hackish, but saves writing another parser
+
+ /*
+ 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
+ mse | 3 | 0 | localhost:4565
+ mse | 3 | 11 | locahost:5511
+ mse | 3 | -1 | localhost:5500
+ */
+ gcounts[0] = 1; // first entry has 1 group with 2 endpoints; message type 0, sid 0
ecounts[0] = 2;
- mtypes[0] = 0;
+ mtypes[0] = build_key( 0, 0 ); // mtype is now a key of mtype/sid
entries[enu].group = 0; entries[enu].ep_name = "yahoo.com:4561"; enu++; // use a dns resolvable name to test that
- entries[enu].group = 0; entries[enu].ep_name = "localhost:4562"; enu++; // rest can default to some dummy ip
+ entries[enu].group = 0; entries[enu].ep_name = "localhost:4562"; enu++; // rest can default to some dummy ip
- gcounts[1] = 2;
- ecounts[1] = 3;
- mtypes[1] = 1;
- entries[enu].group = 0; entries[enu].ep_name = "localhost:4561"; enu++;
+ gcounts[1] = 2; // 2 groups
+ ecounts[1] = 3; // first has 3 endpoints
+ mtypes[1] = build_key( 1, 0 );
+ entries[enu].group = 0; entries[enu].ep_name = "localhost:4560"; enu++;
entries[enu].group = 0; entries[enu].ep_name = "localhost:4568"; enu++;
entries[enu].group = 0; entries[enu].ep_name = "localhost:4569"; enu++;
- gcounts[2] = 0; // 0 groups means use same rte, this is the next gropup
- ecounts[2] = 2;
- mtypes[2] = 1;
+ gcounts[2] = 0; // 0 means use same rte, this is the next group for the entry
+ ecounts[2] = 2; // 2 endpoints
+ mtypes[2] = 999; // ignored when appending to previous entry
entries[enu].group = 1; entries[enu].ep_name = "localhost:4561"; enu++;
entries[enu].group = 1; entries[enu].ep_name = "localhost:4562"; enu++;
- gcounts[3] = 1; // 0 groups means use same rte, this is the next gropup
- ecounts[3] = 2;
- mtypes[3] = 2;
+ gcounts[3] = 1; // next entry has 1 group
+ ecounts[3] = 2; // with 2 enpoints
+ mtypes[3] = build_key( 2, 0 );
entries[enu].group = 0; entries[enu].ep_name = "localhost:4563"; enu++;
entries[enu].group = 0; entries[enu].ep_name = "localhost:4564"; enu++;
- gcounts[4] = 1; // 0 groups means use same rte, this is the next gropup
+ gcounts[4] = 1; // three entries for mt==3 with different sids
ecounts[4] = 1;
- mtypes[4] = 3;
- entries[enu].group = 0; entries[enu].ep_name = "localhost:4565"; enu++;
+ mtypes[4] = build_key( 3, 0 );
+ entries[enu].group = 0; entries[enu].ep_name = "localhost:5500"; enu++;
+ gcounts[5] = 1;
+ ecounts[5] = 1;
+ mtypes[5] = build_key( 3, 11 );
+ entries[enu].group = 0; entries[enu].ep_name = "localhost:5511"; enu++;
+
+ gcounts[6] = 1;
+ ecounts[6] = 1;
+ mtypes[6] = build_key( 3, -1 );
+ entries[enu].group = 0; entries[enu].ep_name = "localhost:5512"; enu++;
rt = uta_rt_init( ); // get us a route table
@@ -178,6 +214,9 @@
}
}
+ // ----- end hacking together a route table ---------------------------------------------------
+
+
crt = uta_rt_clone( rt ); // clone only the endpoint entries
errors += fail_if_nil( crt, "cloned route table" );
if( crt ) {
@@ -216,31 +255,70 @@
//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" );
+
+ // --- 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
+ errors += fail_if_nil( rte, "get_rte did not return a pointer when s=0 m=1 true given" );
+
+ rte = uta_get_rte( rt, 0, 1, FALSE ); // the retry shouldn't apply, but ensure it does the righ thing
+ errors += fail_if_nil( rte, "get_rte did not return a pointer when s=0 m=1 false given" );
+
+ rte = uta_get_rte( rt, 1000, 1, FALSE ); // s=1000 does not exist for any msg type; should return nil as not allowed to drop sid
+ errors += fail_not_nil( rte, "get_rte returned a pointer when s=1000 m=1 false given" );
+
+ rte = uta_get_rte( rt, 1000, 1, TRUE ); // this should also fail as there is no mt==1 sid==-1 defined
+ errors += fail_not_nil( rte, "get_rte returned a pointer when s=1000 m=1 true given" );
+
+ rte = uta_get_rte( rt, 0, 3, TRUE ); // mtype sid combo does exist; true/false should not matter
+ errors += fail_if_nil( rte, "get_rte did not return a pointer when s=0 m=3 true given" );
+
+ rte2 = uta_get_rte( rt, 11, 3, TRUE ); // same mtype as before, different (valid) group, rte should be different than before
+ errors += fail_if_nil( rte2, "get_rte did not return a pointer when s=11 m=3 true given" );
+ errors += fail_if_true( rte == rte2, "get_rte for mtype==3 and different sids (0 and 11) returned the same rte pointer" );
+
+ rte2 = uta_get_rte( rt, 0, 3, FALSE ); // since the mtype/sid combo exists, setting false should return the same as before
+ errors += fail_if_nil( rte2, "get_rte did not return a pointer when s=0 m=3 false given" );
+ errors += fail_if_false( rte == rte2, "get_rte did not return same pointer when mtype/sid combo given with different true/false" );
+
+ 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
+ errors += fail_if_nil( rte, "get_rte did not return a pointer for s=12, m=3, true" );
+
alt_value = -1;
- for( i = 0; i < 10; i++ ) { // round robin return value should be different each time
- value = uta_epsock_rr( rt, 1, 0, &more, &nn_sock ); // msg type 1, group 1
- 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, 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 ); // msg type 1, group 1
+ 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;
+ }
}
more = -1;
- for( i = 0; i < 10; i++ ) { // this mtype has only one endpoint, so rr should be same each time
- value = uta_epsock_rr( rt, 3, 0, NULL, &nn_sock ); // also test ability to deal properly with nil more pointer
- 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, 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 ); // also test ability to deal properly with nil more pointer
+ 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" );
+ }
+ alt_value = value;
}
- alt_value = value;
}
- value = uta_epsock_rr( rt, 9, 0, &more, &nn_sock ); // non-existant message type; should return false (0)
- errors += fail_not_equal( value, 0, "socket for bad mtype was valid" );
+ rte = uta_get_rte( rt, 11, 3, TRUE );
+ state = uta_epsock_rr( rte, 22, NULL, NULL );
+ 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_drop( NULL );
- uta_epsock_rr( NULL, 1, 0, &more, &nn_sock ); // drive null case for coverage
+ uta_epsock_rr( NULL, 0, &more, &nn_sock ); // drive null case for coverage
uta_add_rte( NULL, 99, 1 );
+ uta_get_rte( NULL, 0, 1000, TRUE );
fprintf( stderr, "[INFO] test: adding end points with nil data; warnings expected\n" );
uta_add_ep( NULL, NULL, "foo", 1 );
@@ -258,25 +336,26 @@
}
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 ) {
- if( ! (fail_if_nil( rt, "pointer to rt for load test" )) ) {
- errors++;
- read_static_rt( ctx, 0 );
- unsetenv( "RMR_SEED_RT" ); // unset to test the does not exist condition
- read_static_rt( ctx, 0 );
- } else {
- fprintf( stderr, "<FAIL> cannot gen rt for load test\n" );
- }
- } else {
- read_static_rt( ctx, 0 ); // not defined, just drive for that one case
+ 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
}
+
+ read_static_rt( ctx, 0 ); // drive for not there coverage
}
- uta_fib( "no-suhch-file" ); // drive some error checking for coverage
+
+ buf = uta_fib( "no-suhch-file" ); // drive some error checking for coverage
+ if( buf ) {
+ free( buf );
+ }
ep = (endpoint_t *) malloc( sizeof( *ep ) );
@@ -286,12 +365,6 @@
state = uta_link2( ep );
errors += fail_if_true( state, "link2 did not return false when given nil pointers" );
- state = uta_epsock_rr( rt, 122, 0, NULL, NULL );
- errors += fail_if_true( state, "uta_epsock_rr returned bad state when given nil socket pointer" );
-
- rt = uta_rt_init( ); // get us a route table
- state = uta_epsock_rr( rt, 0, -1, NULL, &nn_sock );
- errors += fail_if_true( state, "uta_epsock_rr returned bad state (true) when given negative group number" );
return !!errors; // 1 or 0 regardless of count
}