Correct table clear bug in route table ready
[ric-plt/lib/rmr.git] / test / rmr_nng_api_static_test.c
index 2db1a20..6588907 100644 (file)
 #include <errno.h>
 #include <string.h>
 #include <stdint.h>
+#include <pthread.h>
+#include <semaphore.h>
 
-#include "../src/common/include/rmr.h"
-#include "../src/common/include/rmr_agnostic.h"
+#include "rmr.h"
+#include "rmr_agnostic.h"
 
 /*
        Send a 'burst' of messages to drive some send retry failures to increase RMr coverage
@@ -84,6 +86,22 @@ static void send_n_msgs( void* ctx, int n ) {
        }
 }
 
+/*
+       Refresh or allocate a message with some default values
+*/
+static rmr_mbuf_t* fresh_msg( void* ctx, rmr_mbuf_t* msg ) {
+       if( ! msg )  {
+               msg = rmr_alloc_msg( ctx, 2048 );
+       }
+
+       msg->mtype = 0;
+       msg->sub_id = -1;
+       msg->state = 0;
+       msg->len = 100;
+
+       return msg;
+}
+
 static int rmr_api_test( ) {
        int             errors = 0;
        void*   rmc;                            // route manager context
@@ -98,28 +116,46 @@ static int rmr_api_test( ) {
        v = rmr_ready( NULL );
        errors += fail_if( v != 0, "rmr_ready returned true before initialisation "  );
 
+       em_set_long_hostname( 1 );
        if( (rmc = rmr_init( "4560", 1024, FL_NOTHREAD )) == NULL ) {
                fail_if_nil( rmc, "rmr_init returned a nil pointer "  );
                return 1;
        }
 
+       setenv( "RMR_SRC_ID", "somehost", 1 );                                                          // context should have this as source
        if( (rmc2 = rmr_init( ":6789", 1024, FL_NOTHREAD )) == NULL ) {         // init without starting a thread
                errors += fail_if_nil( rmc, "rmr_init returned a nil pointer for non-threaded init "  );
        }
 
+       fprintf( stderr, "<INFO> with RMR_SRC_ID env set, source name in context: (%s)\n", ((uta_ctx_t *) rmc2)->my_name );
+       v = strcmp( ((uta_ctx_t *) rmc2)->my_name, "somehost:6789" );
+       errors += fail_not_equal( v, 0, "source name not set from environment variable (see previous info)" );
        free_ctx( rmc2 );                       // coverage
-
+       
+       unsetenv( "RMR_SRC_ID" );                                                                                               // context should NOT have our artificial name 
        if( (rmc2 = rmr_init( NULL, 1024, FL_NOTHREAD )) == NULL ) {                    // drive default port selector code
                errors += fail_if_nil( rmc, "rmr_init returned a nil pointer when driving for default port "  );
        }
 
+       fprintf( stderr, "<INFO> after unset of RMR_SRC_ID, source name in context: (%s)\n", ((uta_ctx_t *) rmc2)->my_name );
+       v = strcmp( ((uta_ctx_t *) rmc2)->my_name, "somehost:6789" );
+       errors += fail_if_equal( v, 0, "source name smells when removed from environment (see previous info)" );
+       free_ctx( rmc2 );                       // attempt to reduce leak check errors
+
        v = rmr_ready( rmc );           // unknown return; not checking at the moment
 
        msg = rmr_alloc_msg( NULL,  1024 );                                                                     // should return nil pointer
        errors += fail_not_nil( msg, "rmr_alloc_msg didn't return nil when given nil context "  );
 
+       
        msg = rmr_alloc_msg( rmc, 2048 );                               // allocate larger than default size given on init
        errors += fail_if_nil( msg, "rmr_alloc_msg returned nil msg pointer "  );
+       if( msg ) {
+               rmr_get_srcip( msg, wbuf );
+               errors += fail_if_equal( 0, strlen( wbuf ), "rmr_get_srcip did not did not return string with length (b) after alloc_msg" );
+               fprintf( stderr, "<INFO> ip: %s\n", wbuf );
+       }
+
 
        v = rmr_payload_size( NULL );
        errors += fail_if( v >= 0, "rmr_payload_size returned valid size for nil message "  );
@@ -157,12 +193,14 @@ static int rmr_api_test( ) {
        msg->len = 100;
        msg->mtype = 1;
        msg->state = 999;
+       msg->tp_state = 999;
        errno = 999;
        msg = rmr_send_msg( rmc, msg );
        errors += fail_if_nil( msg, "send_msg_ did not return a message on send "  );
        if( msg ) {
                errors += fail_not_equal( msg->state, RMR_ERR_NOENDPT, "send_msg did not return no endpoints before rtable added "  );
                errors += fail_if( errno == 0, "send_msg did not set errno "  );
+               errors += fail_if( msg->tp_state == 999, "send_msg did not set tp_state (1)" );
        }
 
        gen_rt( rmc );          // --- after this point there is a dummy route table so send and rts calls should be ok
@@ -170,6 +208,7 @@ static int rmr_api_test( ) {
        msg->len = 100;
        msg->mtype = 1;
        msg->state = 999;
+       msg->tp_state = 999;
        errno = 999;
        msg = rmr_send_msg( rmc, msg );
        errors += fail_if_nil( msg, "send_msg_ did not return a message on send "  );
@@ -178,6 +217,7 @@ static int rmr_api_test( ) {
                errors += fail_if( errno != 0, "send_msg set errno for send that should work "  );
                v = rmr_payload_size( msg );
                errors += fail_if( v != 2048, "send_msg did not allocate new buffer with correct size "  );
+               errors += fail_if( msg->tp_state == 999, "send_msg did not set tp_state (2)" );
        }
 
        rmr_set_stimeout( NULL, 0 );
@@ -196,7 +236,6 @@ static int rmr_api_test( ) {
                if( msg2->state != RMR_ERR_EMPTY ) {
                        errors += fail_not_equal( msg2->state, RMR_OK, "receive given nil message did not return msg with good state (not empty) "  );
                }
-               //errors += fail_not_equal( msg2->state, RMR_OK, "receive given nil message did not return msg with good state "  );
        }
 
 
@@ -214,12 +253,17 @@ static int rmr_api_test( ) {
 
        msg->state = 0;
        msg = rmr_rts_msg( NULL, msg );                 // should set state in msg
-       errors += fail_if_equal( msg->state, 0, "rmr_rts_msg did not set state when given valid message but no context "  );
+       if( msg ) {
+               errors += fail_if_equal( msg->state, 0, "rmr_rts_msg did not set state when given valid message but no context "  );
+       } else {
+               errors += fail_if_nil( msg,  "rmr_rts_msg returned a nil msg when given a good one" );
+       }
 
 
        msg = rmr_rts_msg( rmc, msg );                  // return the buffer to the sender
        errors += fail_if_nil( msg, "rmr_rts_msg did not return a message pointer "  );
-       errors += fail_if( errno != 0, "rmr_rts_msg did not reset errno "  );
+       errors += fail_not_equal( msg->state, 0, "rts_msg did not return a good state (a) when expected" );
+       errors += fail_not_equal( errno, 0, "rmr_rts_msg did not reset errno (a) expected (b)"  );
 
 
 
@@ -230,6 +274,8 @@ static int rmr_api_test( ) {
        snprintf( msg->xaction, 17, "%015d", 16 );              // dummy transaction id (emulation generates, this should arrive after a few calls to recv)
        msg->mtype = 0;
        msg->sub_id = -1;
+       em_set_rcvcount( 0 );                                                   // reset message counter
+       em_set_rcvdelay( 1 );                                                   // force slow msg rate during mt testing
        msg = rmr_call( rmc, msg );                                             // dummy nng/nano function will sequentually add xactions and should match or '16'
        errors += fail_if_nil( msg, "rmr_call returned a nil message on call expected to succeed "  );
        if( msg ) {
@@ -285,7 +331,7 @@ static int rmr_api_test( ) {
        errors += fail_if( i >= 40, "torcv_msg never returned a timeout "  );
 
 
-       // ---- trace things that are not a part of the mbuf_api functions and thus must be tested here
+       // ---- trace things that are not a part of the mbuf_api functions and thus must be tested here -------
        state = rmr_init_trace( NULL, 37 );                                             // coverage test nil context
        errors += fail_not_equal( state, 0, "attempt to initialise trace with nil context returned non-zero state (a) "  );
        errors += fail_if_equal( errno, 0, "attempt to initialise trace with nil context did not set errno as expected "  );
@@ -306,10 +352,114 @@ static int rmr_api_test( ) {
        em_send_failures = 0;
 
 
+       ((uta_ctx_t *)rmc)->shutdown = 1;
        rmr_close( NULL );                      // drive for coverage
        rmr_close( rmc );                       // no return to check; drive for coverage
 
 
+       // -- allocate a new context for mt-call and drive that stuff -----------------------------------------
+#ifdef EMULATE_NNG
+       msg = fresh_msg( rmc, msg );                                                    // ensure we have one with known contents
+
+       msg->state = 0;
+       msg = rmr_mt_call( rmc, msg, 3, 10 );                                                   // drive when not in mt setup
+       if( msg ) {
+               errors += fail_not_equal( msg->state, RMR_ERR_NOTSUPP, "rmr_mt_call did not set not supported error when not mt initialised" );
+       } else {
+               errors += fail_if_nil( msg, "rmr_mt_call returned nil pointer when not mt initialised" );
+       }
+       msg = fresh_msg( rmc, msg );
+
+       msg = rmr_mt_rcv( rmc, msg, 10 );                                                               // gen not supported error if ctx not set for mt
+       if( msg ) {
+               errors += fail_not_equal( msg->state, RMR_ERR_NOTSUPP, "rmr_mt_rcv did not return not supported state when mt not initialised" );
+       } else {
+               errors += fail_if_nil( msg, "nil pointer from rmr_mt_rcv when mt not initialised\n" );
+       }
+       msg = fresh_msg( rmc, msg );
+
+       msg->state = 0;
+       if( msg ) {
+               msg = rmr_mt_call( rmc, msg, 1000, 10 );                                                        // thread id out of range
+               errors += fail_if_equal( msg->state, 0, "rmr_mt_call did not set an error when given an invalid call-id" );
+       } else {
+               errors += fail_if_nil( msg, "rmr_mt_call returned a nil pointer when given an invalid call-id" );
+       }
+       msg = fresh_msg( rmc, msg );
+
+       state = init_mtcall( NULL );                                    // drive for coverage
+       errors += fail_not_equal( state, 0, "init_mtcall did not return false (a) when given a nil context pointer" );
+
+
+       if( (rmc = rmr_init( NULL, 1024, FL_NOTHREAD | RMRFL_MTCALL )) == NULL ) {                      // drive multi-call setup code without rtc thread
+               errors += fail_if_nil( rmc, "rmr_init returned a nil pointer when driving for mt-call setup "  );
+       }
+
+       gen_rt( rmc );                                                                  // must attach a route table so sends succeed
+
+       fprintf( stderr, "<INFO> enabling mt messages\n" );
+       em_set_rcvdelay( 1 );                                                   // force slow msg rate during mt testing
+       em_set_mtc_msgs( 1 );                                                   // emulated nngrcv will now generate messages with call-id and call flag
+
+       msg->state = 0;
+       msg = rmr_mt_call( NULL, msg, 3, 10 );                  // should timeout
+       if( msg ) {
+               errors += fail_if( msg->state == 0, "rmr_mt_call did not set message state when given message with nil context "  );
+       }
+       msg = fresh_msg( rmc, msg );
+
+       fprintf( stderr, "<INFO> invoking mt_call with timout == 2999\n" );
+       msg = rmr_mt_call( rmc, msg, 2, 2999 );                 // long timeout to drive time building code, should receive
+       if( msg ) {
+               if( msg->state != RMR_OK ) {
+                       fprintf( stderr, "<INFO> rmr_mt_call returned error in mbuf: %d\n", msg->state );
+               } else {
+                       errors += fail_not_nil( msg, "rmr_mt_call did not return a nil pointer on read timeout" );
+               }
+       }
+       msg = fresh_msg( rmc, msg );
+
+       msg = rmr_mt_rcv( NULL, NULL, 10 );
+       errors += fail_not_nil( msg, "rmr_mt_rcv returned a non-nil message when given nil message and nil context" );
+
+       fprintf( stderr, "<INFO> invoking mt_rcv with timout == 2999\n" );
+       msg = fresh_msg( rmc, msg );
+       msg = rmr_mt_rcv( rmc, msg, 2999 );
+       if( !msg ) {
+               errors += fail_if_nil( msg, "rmr_mt_rcv returned a nil message when given valid message and timeout of 29999" );
+       }
+       msg = fresh_msg( rmc, msg );
+
+       msg = rmr_mt_rcv( rmc, msg, -1 );
+       if( !msg ) {
+               errors += fail_if_nil( msg, "rmr_mt_rcv returned a nil message when given valid message unlimited timeout" );
+       }
+       msg = fresh_msg( rmc, msg );
+
+       fprintf( stderr, "<INFO> waiting 20.0 seconds for a known call xaction to arrive (%ld)\n", time( NULL ) );
+       snprintf( msg->xaction, 17, "%015d", 5 );               // we'll reset receive counter before calling mt_call so this will arrive again
+       em_set_rcvcount( 0 );
+       msg = rmr_mt_call( rmc, msg, 2, 15000 );                // we need about 10s to get the message with the 'slow rate'
+       if( msg ) {
+               errors += fail_not_equal( msg->state, RMR_OK, "mt_call with known xaction id bad state (a)" );
+       } else {
+               errors += fail_if_nil( msg, "mt_call with known xaction id returned nil message" );
+       }
+       fprintf( stderr, "<INFO> time check: %ld\n", time( NULL ) );
+
+       em_set_mtc_msgs( 0 );                                                   // turn off 
+       em_set_rcvdelay( 0 );                                                   // full speed receive rate to overflow the ring
+
+       fprintf( stderr, "<INFO> pausing 5s to allow mt-call receive ring to fill  %ld\n", time( NULL ) );
+       sleep( 2 );
+       fprintf( stderr, "<INFO> tests continuing %ld\n", time( NULL ) );
+       em_set_rcvdelay( 1 );                                                   // restore slow receive pace for any later tests
+       ((uta_ctx_t *)rmc)->shutdown = 1;                               // force the mt-reciver attached to the context to stop
+#endif
+
+
+       // --------------- phew, done ------------------------------------------------------------------------------
+
        if( ! errors ) {
                fprintf( stderr, "<INFO> all RMr API tests pass\n" );
        }