Beef up unit tests for SI95 code
[ric-plt/lib/rmr.git] / test / rmr_si_api_static_test.c
index e50a987..2e2b7c7 100644 (file)
@@ -1,8 +1,8 @@
 // : vi ts=4 sw=4 noet :
 /*
 ==================================================================================
-           Copyright (c) 2019-2020 Nokia
-           Copyright (c) 2018-2020 AT&T Intellectual Property.
+           Copyright (c) 2019-2021 Nokia
+           Copyright (c) 2018-2021 AT&T Intellectual Property.
 
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
                                         rmr_mtosend_msg
                                         rmr_free_msg
 
+                               Not all message/call functions can be tested here because of the
+                               callback nature of SI.  There is a specific rcv test static module
+                               for those tests.
+
        Author:         E. Scott Daniels
        Date:           5 April 2019
 */
 #include "rmr_agnostic.h"
 
 /*
-       Send a 'burst' of messages to drive some send retry failures to increase RMr coverage
-       by handling the retry caee.
+       Driving ep counts is tricky when trying to do it as a part of the rts function, so
+       we drive that code on it's own.
 */
-static void send_n_msgs( void* ctx, int n ) {
-       rmr_mbuf_t*     msg;                    // message buffers
-       int i;
+static int test_ep_counts() {
+       int errors = 0;
+       struct endpoint ep;                     // need a dummy endpoint
 
-       msg = rmr_alloc_msg( ctx,  1024 );
-       if( ! msg ) {
-               return;
-       }
+       memset( &ep, 0, sizeof( ep ) );
 
-       for( i = 0; i < n; i++ ) {
-               //fprintf( stderr, "mass send\n" );
-               msg->len = 100;
-               msg->mtype = 1;
-               msg->state = 999;
-               errno = 999;
-               msg = rmr_send_msg( ctx, msg );
-       }
-}
+       incr_ep_counts( RMR_OK, &ep );
+       errors += fail_if_false(  ep.scounts[EPSC_GOOD] == 1, "ep inc good counter had bad value" );
 
-/*
-       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 );
-       }
+       incr_ep_counts( RMR_ERR_RETRY, &ep );
+       errors += fail_if_false(  ep.scounts[EPSC_TRANS] == 1, "ep inc trans counter had bad value" );
 
-       msg->mtype = 0;
-       msg->sub_id = -1;
-       msg->state = 0;
-       msg->len = 100;
+       incr_ep_counts( 99, &ep );                              // any non-retry/ok value
+       errors += fail_if_false(  ep.scounts[EPSC_FAIL] == 1, "ep inc fail counter had bad value" );
 
-       return msg;
+       incr_ep_counts( RMR_OK, NULL );                 // ensure nil pointer doesn't crash us
+
+       return errors;
 }
 
 static int rmr_api_test( ) {
@@ -110,8 +99,10 @@ static int rmr_api_test( ) {
        int             v = 0;                                  // some value
        char    wbuf[128];
        int             i;
+       void*   p;                                      // generic pointer to test return value
        int             state;
        int             max_tries;                      // prevent a sticking in any loop
+       uta_ctx_t* ctx;
 
        v = rmr_ready( NULL );
        errors += fail_if( v != 0, "rmr_ready returned true before initialisation "  );
@@ -131,8 +122,8 @@ static int rmr_api_test( ) {
        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 
+
+       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 "  );
        }
@@ -147,7 +138,7 @@ static int rmr_api_test( ) {
        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 ) {
@@ -245,9 +236,8 @@ static int rmr_api_test( ) {
                max_tries--;
        }
 
-
        // ----- the queue load and disc cb tests should be last! -----------------------------
-       for( i = 0; i < 4000; i++ ) {                   // test ring drop 
+       for( i = 0; i < 4000; i++ ) {                   // test ring drop
                if( msg == NULL ) {
                        msg = rmr_alloc_msg( rmc, 2048 );                               // get a buffer with a transport header
                }
@@ -265,109 +255,6 @@ static int rmr_api_test( ) {
        mt_disc_cb( rmc, 0 );                   // disconnect callback for coverage
        mt_disc_cb( rmc, 100 );                 // with a fd that doesn't exist
 
-return errors;
-
-       msg2 = rmr_rcv_msg( NULL, NULL );
-       errors += fail_if( msg2 != NULL, "rmr_rcv_msg returned msg when given nil context and msg "  );
-
-       msg2 = rmr_rcv_msg( rmc, NULL );
-       errors += fail_if( msg2 == NULL, "rmr_rcv_msg returned nil msg when given nil msg "  );
-       if( msg2 ) {
-               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) "  );
-               }
-       }
-
-
-       msg = rmr_rcv_msg( rmc, msg );
-       if( msg ) {
-               errors += fail_not_equal( msg->state, RMR_OK, "rmr_rcv_msg did not return an ok state "  );
-               errors += fail_not_equal( msg->len, 220, "rmr_rcv_msg returned message with invalid len "  );
-       } else {
-               errors += fail_if_nil( msg, "rmr_rcv_msg returned a nil pointer "  );
-       }
-
-       rmr_rts_msg( NULL, NULL );                      // drive for coverage
-       rmr_rts_msg( rmc, NULL );
-       errors += fail_if( errno == 0, "rmr_rts_msg did not set errno when given a nil message "  );
-
-       msg->state = 0;
-       msg = rmr_rts_msg( NULL, msg );                 // should set state in msg
-       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_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)"  );
-
-       msg->state = 0;
-       msg = rmr_call( NULL, msg );
-       errors += fail_if( msg->state == 0, "rmr_call did not set message state when given message with nil context "  );
-
-       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 ) {
-               errors += fail_not_equal( msg->state, RMR_OK, "rmr_call did not properly set state on successful return "  );
-               errors += fail_not_equal( errno, 0, "rmr_call did not properly set errno (a) on successful return "  );
-       }
-
-       snprintf( wbuf, 17, "%015d", 14 );                              // while waiting, the queued messages should have #14, so issue a few receives looking for it
-       for( i = 0; i < 16; i++ ) {                                             // it should be in the first 15
-               msg = rmr_rcv_msg( rmc, msg );
-               if( msg ) {
-                       if( strcmp( wbuf, msg->xaction ) == 0 ) {               // found the queued message
-                               break;
-                       }
-                       fprintf( stderr, "<INFO> msg: %s\n", msg->xaction );
-               } else {
-                       errors += fail_if_nil( msg, "receive returnd nil msg while looking for queued message "  );
-               }
-       }
-
-       errors += fail_if( i >= 16, "did not find expected message on queue "  );
-
-       if( ! msg ) {
-               msg = rmr_alloc_msg( rmc, 2048 );                               // something buggered above; get a new one
-       }
-       msg->mtype = 0;
-       msg->sub_id = -1;
-       msg = rmr_call( rmc, msg );                                                     // make a call that we never expect a response on (nil pointer back)
-       errors += fail_not_nil( msg, "rmr_call returned a nil message on call expected not to receive a response "  );
-       errors += fail_if( errno == 0, "rmr_call did not set errno on failure "  );
-
-       rmr_free_msg( NULL );                   // drive for coverage; nothing to check
-       rmr_free_msg( msg2 );
-
-
-       msg2 = rmr_torcv_msg( NULL, NULL, 10 );
-       errors += fail_not_nil( msg2, "rmr_torcv_msg returned a pointer when given nil information "  );
-       msg2 = rmr_torcv_msg( rmc, NULL, 10 );
-       errors += fail_if_nil( msg2, "rmr_torcv_msg did not return a message pointer when given a nil old msg "  );
-
-       // ---  test timeout receive; our dummy epoll function will return 1 ready on first call and 0 ready (timeout emulation) on second
-       //              however we must drain the swamp (queue) first, so run until we get a timeout error, or 20 and report error if we get to 20.
-       msg = NULL;
-       for( i = 0; i < 40; i++ ) {
-               msg = rmr_torcv_msg( rmc, msg, 10 );
-               errors += fail_if_nil( msg, "torcv_msg returned nil msg when message expected "  );
-               if( msg ) {
-                       if( msg->state == RMR_ERR_TIMEOUT || msg->state == RMR_ERR_EMPTY ) {            // queue drained and we've seen both states from poll if we get a timeout
-                               break;
-                       }
-               }
-       }
-       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 -------
        state = rmr_init_trace( NULL, 37 );                                             // coverage test nil context
@@ -395,11 +282,75 @@ return errors;
        rmr_close( rmc );                       // no return to check; drive for coverage
 
 
+       // ----- mt_rcv edge cases -------------------------------------------------------------------------------------
+       ctx = mk_dummy_ctx();
+       p = rmr_mt_rcv( NULL, msg, 0 );                         // give a valid message to cover additional lines
+       errors += fail_if_nil( p, "rmr_rt_rcv did not pointer when given a message with a nil context" );
+       if( msg ) {
+               errors += fail_if_equal( msg->state, RMR_OK, "rmr_mt_rcv returned OK state when given nil context" );
+       }
+
+       p = rmr_mt_rcv( ctx, msg, 0 );                          // one shot receive "poll" case
+       errors += fail_if_nil( p, "mt_rcv with one shot time length did not return a pointer" );
+
+
+       // --------------- nil pointer exception checks ----------------------------------------------------------------
+       rmr_rcv_specific( NULL, NULL, "foo", 0 );
+       mt_call( NULL, NULL, 0, 1, NULL );
+       rmr_mt_call( NULL, NULL, 0, 1 );
+       rmr_set_low_latency( NULL );
+       rmr_set_fack( NULL );
+
+
+       msg2 = rmr_alloc_msg( rmc,  1024 );
+       msg2 = rmr_rcv_msg( NULL, msg2 );
+       if( msg2 != NULL ) {
+               errors += fail_if( msg2->state == RMR_OK, "nil context check for rcv msg returned OK" );
+       }
+       msg2 = rmr_torcv_msg( NULL, msg2, 200 );
+       if( msg2 != NULL ) {
+               errors += fail_if( msg2->state == RMR_OK, "nil context check for torcv msg returned OK" );
+       }
+
+       //  ----- thread start coverage ---------------------------------------------------------------------------
+       setenv( "RMR_WARNINGS", "1", 1 );       // force non-default branches during these tests
+       setenv( "RMR_SRC_NAMEONLY", "1", 1 );
+
+       rmr_init( ":6789", 1024, 0 );           // threaded mode with defined/default RM target
+       setenv( "RMR_RTG_SVC", "-1", 1 );       // force into static table mode
+       rmr_init( ":6789", 1024, 0 );           // threaded mode with static table
+
+
+       // ---- some things must be pushed specifically for edge cases and such ------------------------------------
+       errors += test_ep_counts();
+       init_err( "test error message", rmc, rmc2, ENOMEM );            // drive for coverage
+
+       ctx = mk_dummy_ctx();
+       ctx->river_hash = rmr_sym_alloc( 129 );
+
+       buf2mbuf( NULL, NULL, 0, 0 );                                                           // things in mt_call_si_static
+
+       state = mt_data_cb( NULL, 0, "123", 3 );
+       errors += fail_not_equal( state, 0, "mt_data_cb didn't respond correctly when ctx is nil" );
+
+       state = mt_data_cb( ctx, -1, "123", 3 );
+       errors += fail_not_equal( state, 0, "mt_data_cb didn't respond correctly when ctx is nil" );
+
+       ctx->nrivers = 1;
+       state = mt_data_cb( ctx, 23, "123", 3 );                                        // force add river to hash reference
+       errors += fail_not_equal( state, 0, "mt_data_cb didn't respond correctly when ctx is nil" );
+
+       mt_disc_cb( NULL, 0 );
+       mt_disc_cb( ctx, 128 );                                 // for a FD we know isn't there
+
+
+       p = mt_receive( NULL );
+       errors += fail_not_nil( p, "mt_receive returned non-nil pointer when given nil context" );
 
        // --------------- phew, done ------------------------------------------------------------------------------
 
        if( ! errors ) {
                fprintf( stderr, "<INFO> all RMr API tests pass\n" );
        }
-       return !!errors;
+       return errors;
 }