X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=test%2Frt_static_test.c;h=9559004d06dab3cf55f6928964b6ecb14bf1b65b;hb=bf897297010df539909b7638d96557d41fd217b0;hp=129eec1da669b436f5b7793fb318dc415f4d348c;hpb=8790bf0c4f4f08fd05853afa67e211112b344a42;p=ric-plt%2Flib%2Frmr.git diff --git a/test/rt_static_test.c b/test/rt_static_test.c index 129eec1..9559004 100644 --- a/test/rt_static_test.c +++ b/test/rt_static_test.c @@ -1,7 +1,7 @@ // : vi ts=4 sw=4 noet : /* ================================================================================== - Copyright (c) 2019 Nokia + Copyright (c) 2019 Nokia Copyright (c) 2018-2019 AT&T Intellectual Property. Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,7 +21,7 @@ /* Mmemonic: rt_static_test.c Abstract: Test the route table funcitons. These are meant to be included at compile - time by the test driver. + time by the test driver. Author: E. Scott Daniels Date: 3 April 2019 @@ -34,9 +34,11 @@ #include #include #include +#include +#include -#include "../src/common/include/rmr.h" -#include "../src/common/include/rmr_agnostic.h" +#include "rmr.h" +#include "rmr_agnostic.h" typedef struct entry_info { int group; @@ -44,6 +46,51 @@ typedef struct entry_info { } ei_t; +/* + Driven by symtab foreach element of one space. + We count using the data as a counter. +*/ +static void count_things( void* st, void* entry, char const* name, void* thing, void* vdata ) { + int* counter; + + if( thing ) { + if( (counter = (int *) vdata) != NULL ) { + *counter++; + } + } +} + +/* + Returns the number of entries in the table for the given class. +*/ +static int count_entries( route_table_t* rt, int class ) { + int counter = 0; + + if( ! rt ) { + return 0; + } + if( !rt->hash ) { + return 0; + } + + rmr_sym_foreach_class( rt->hash, class, count_things, &counter ); // run each and update counter + + return counter; +} + +/* + 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, " 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 @@ -53,19 +100,22 @@ static int rt_test( ) { 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 int i; int k; + int c1; // general counters + int c2; int mtype; 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; @@ -73,44 +123,67 @@ static int rt_test( ) { char *buf; char* seed_fname; // seed file nng_socket nn_sock; // this is a struct in nng, so difficult to validate + rmr_mbuf_t* mbuf; // message for meid route testing 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 @@ -142,44 +215,114 @@ static int rt_test( ) { } } - crt = uta_rt_clone( rt ); + // ----- 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 ) { + 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" ); + uta_rt_drop( crt ); + } + + + crt = uta_rt_clone_all( rt ); // clone all entries + 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)" ); + uta_rt_drop( crt ); + } + ep = uta_get_ep( rt, "localhost:4561" ); errors += fail_if_nil( ep, "end point (fetch by name)" ); ep = uta_get_ep( rt, "bad_name:4560" ); errors += fail_not_nil( ep, "end point (fetch by name with bad name)" ); - state = uta_epsock_byname( rt, "localhost:4561", &nn_sock ); // this should be found + ep = NULL; + state = uta_epsock_byname( rt, "localhost:4561", &nn_sock, &ep ); // this should be found 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" ); + + // --- 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, &ep ); // 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, &ep ); // 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, &ep ); + 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, &ep ); // 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 ); @@ -197,36 +340,54 @@ static int rt_test( ) { } uta_rt_drop( rt ); - - uta_rt_drop( crt ); + 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, " 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 -/* - if( ctx ) { - if( ctx->rtg_addr ) { - free( ctx->rtg_addr ); - } - free( ctx ); + buf = uta_fib( "no-suhch-file" ); // drive some error checking for coverage + if( buf ) { + free( buf ); } -*/ + + + ep = (endpoint_t *) malloc( 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" ); + + // ----------------- test the meid support for looking up an endpoint based on the meid in the message ----- + + 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 = rmr_alloc_msg( ctx, 2048 ); // buffer to play with + mbuf->len = 100; + rmr_str2meid( mbuf, "meid1" ); // id that we know is in the map + + 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" ); return !!errors; // 1 or 0 regardless of count }