Remove NNG libraries from packages 68/3368/8
authorE. Scott Daniels <daniels@research.att.com>
Tue, 21 Apr 2020 16:51:05 +0000 (12:51 -0400)
committerE. Scott Daniels <daniels@research.att.com>
Wed, 22 Apr 2020 14:25:38 +0000 (10:25 -0400)
The default build process will no longer include the NNG
libraries (librmr_nng.*) by default.  It is still possible
to enable them with a CMake build flag (-DBUILD_NNG=1).

The NNG specific unit tests have been disabled.

Some SI95 specific unit tests have been enhanced in an effort
to work toward full coverage of the SI95 code.

This change is in a major version bump as the package contents
change. However, there is NOT an API change; all existing
applications will be able to use the new version without any
modification (other than possibly removing references to the
NNG based libraries).

Issue-ID: RIC-337

Signed-off-by: E. Scott Daniels <daniels@research.att.com>
Change-Id: Ic9854b1ffc1e82c765692a11724d8086d24cceed

14 files changed:
CHANGES_CORE.txt
CMakeLists.txt
src/rmr/common/include/RIC_message_types.h
src/rmr/common/src/rtc_static.c
src/rmr/si/src/mt_call_si_static.c
src/rmr/si/src/rmr_si.c
test/Makefile
test/rmr_si_api_static_test.c
test/rmr_si_rcv_static_test.c
test/rt_static_test.c
test/si95_test.c
test/sr_si_static_test.c
test/test_ctx_support.c
test/unit_test.ksh

index 89d0595..481452c 100644 (file)
@@ -5,6 +5,17 @@
 # API and build change  and fix summaries. Doc correctsions
 # and/or changes are not mentioned here; see the commit messages.
 
+2020 April 21; version 4.0.0
+       The NNG based libraries are no longer included in the RMR packages.
+       This is considered a breaking change as NNG will not be supported by
+       default.  It is still possible to build with RMR-NNG libraries, but
+       that is the exception.  The API between 3.8.2 and 4.0.0 is the SAME.
+       Upgrading to 4.0.0 only means that the underlying transport mechanism
+       is limited only to SI95.
+
+       The rmr_rcv_specific() function has been deprecated as it was necessary
+       only for NNG and Nanomsg support.  Its use should be discontinued.
+
 2020 April 20; version 3.8.2
        Fix bug which was preventing an instance receiving dynamic route
        table updates. (RIC-336)
index 3109513..a8aa1ba 100644 (file)
@@ -22,6 +22,7 @@
 #      -DDEBUG=n                       Enable debugging level n
 #      -DDEV_PKG=1                     Development package configuration
 #      -DBUILD_DOC=1           Man pages generated
+#      -DBUILD_NNG=1           Enable building of NNG and the RMR NNG based libraries
 #      -DIGNORE_LIBDIR=1       Installation of rmr libries is into /usr/local/lib and ignores
 #                                              value in CMAKE_INSTALL_LIBDIR.
 #                                              system preferred (typically /usr/local/lib64).
@@ -38,9 +39,9 @@
 project( rmr LANGUAGES C )
 cmake_minimum_required( VERSION 3.5 )
 
-set( major_version "3" )               # should be automatically populated from git tag later, but until CI process sets a tag we use this
-set( minor_version "8" )
-set( patch_level "2" )
+set( major_version "4" )               # should be automatically populated from git tag later, but until CI process sets a tag we use this
+set( minor_version "0" )
+set( patch_level "0" )
 
 set( install_root "${CMAKE_INSTALL_PREFIX}" )
 set( install_inc "include/rmr" )
@@ -50,11 +51,10 @@ else()
        set( install_man "/usr/share/man" )                     # this needs to be fixed so it's not hard coded
 endif()
 
-# Must use GNUInstallDirs to install libraries into correct
-# locations on all platforms.
+# Must use GNUInstallDirs to install libraries into correct locations on all platforms.
 include( GNUInstallDirs )
 
-# nng installs using LIBDIR as established by the gnu include; it varies from system
+# We install using LIBDIR as established by the gnu include; it varies from system
 # to system, and we don't trust that it is always set, so we default to lib if it is missing.
 #
 if( NOT CMAKE_INSTALL_LIBDIR )
@@ -165,56 +165,60 @@ else()
 endif()
 
 # ---------------- setup nano/nng things ---------------------------------------
-if( NOT SKIP_EXTERNALS )
-       set( need_ext 1 )                               # we force dependences on these for right build order
-    execute_process( COMMAND  git submodule update --init -- ext/nng
-            WORKING_DIRECTORY  ${CMAKE_CURRENT_SOURCE_DIR}
-    )
-
-    if( NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/ext/nng/CMakeLists.txt )
-        message( FATAL_ERROR "cannot find nng in our git source as a submodule: Giving up" )   # this will abort which seems wrong, but tdam.
-    endif()
-
-       include( ExternalProject )
-       ExternalProject_Add(
-               ext_nng
-               SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ext/nng"
-               CMAKE_ARGS "-DBUILD_SHARED_LIBS=1"
-               CMAKE_ARGS "-DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}"
-               BUILD_COMMAND "make"
-               UPDATE_COMMAND ""
-               TEST_COMMAND ""
-               STEP_TARGETS build
-       )
-
-       # it seems impossible to install everything that lands in {bin}/lib, so we need to
-       # hard code (shudder) some things. Even worse, we have to make exceptions for
-       # builds on apple (osx) since their naming convention wandered off the path.
-       set( nng_major 1 )
-       set( nng_minor 1.0 )
-       set( so ${CMAKE_SHARED_LIBRARY_SUFFIX} )        # cmake variables are impossibly long :(
-       if( NOT APPLE )                                 # probably breaks in windows, but idc
-               set( nng_so_suffix ${so} )
-               set( nng_so_suffix_m ${so}.${nng_major} )
-               set( nng_so_suffix_mm ${so}.${nng_major}.${nng_minor} )
-       else()
-               # of course apple puts versions before the suffix :(
-               set( nng_so_suffix ${so} )                                                                      # so has a lead dot, so NOT needed
-               set( nng_so_suffix_m ".${nng_major}${so}" )                                     # these need leading dots
-               set( nng_so_suffix_mm ".${nng_major}.${nng_minor}${so}" )
-       endif()
-
-       message( "+++ building with nng: ${nng_major}.${nng_minor}" )
+if( NOT BUILD_NNG )
+       set( PACK_EXTERNALS 0 )
 else()
-       if( PACK_EXTERNALS )
-               # This makes some stand-alone unit testing possible for bindings and transport layer testing;
-               # it is not meant for production packages.
-               #
-               unset( SKIP_EXTERNALS  CACHE )  # must remove so as not to trap user into a never ending failure
-               unset( PACK_EXTERNALS  CACHE )
-               message( FATAL_ERROR "ERROR: PACK_EXTERNALS can be set only if SKIP_EXTERNALS is unset (=0, or not supplied on command line)" )
+       if( NOT SKIP_EXTERNALS )
+               set( need_ext 1 )                               # we force dependences on these for right build order
+               execute_process( COMMAND  git submodule update --init -- ext/nng
+                               WORKING_DIRECTORY  ${CMAKE_CURRENT_SOURCE_DIR}
+               )
+
+               if( NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/ext/nng/CMakeLists.txt )
+                       message( FATAL_ERROR "cannot find nng in our git source as a submodule: Giving up" )    # this will abort which seems wrong, but tdam.
+               endif()
+
+               include( ExternalProject )
+               ExternalProject_Add(
+                       ext_nng
+                       SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ext/nng"
+                       CMAKE_ARGS "-DBUILD_SHARED_LIBS=1"
+                       CMAKE_ARGS "-DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}"
+                       BUILD_COMMAND "make"
+                       UPDATE_COMMAND ""
+                       TEST_COMMAND ""
+                       STEP_TARGETS build
+               )
+
+               # it seems impossible to install everything that lands in {bin}/lib, so we need to
+               # hard code (shudder) some things. Even worse, we have to make exceptions for
+               # builds on apple (osx) since their naming convention wandered off the path.
+               set( nng_major 1 )
+               set( nng_minor 1.0 )
+               set( so ${CMAKE_SHARED_LIBRARY_SUFFIX} )        # cmake variables are impossibly long :(
+               if( NOT APPLE )                                                         # probably breaks in windows, but idc
+                       set( nng_so_suffix ${so} )
+                       set( nng_so_suffix_m ${so}.${nng_major} )
+                       set( nng_so_suffix_mm ${so}.${nng_major}.${nng_minor} )
+               else()
+                       # of course apple puts versions before the suffix :(
+                       set( nng_so_suffix ${so} )                                                                      # so has a lead dot, so NOT needed
+                       set( nng_so_suffix_m ".${nng_major}${so}" )                                     # these need leading dots
+                       set( nng_so_suffix_mm ".${nng_major}.${nng_minor}${so}" )
+               endif()
+
+               message( "+++ building with nng: ${nng_major}.${nng_minor}" )
+       else()
+               if( PACK_EXTERNALS )
+                       # This makes some stand-alone unit testing possible for bindings and transport layer testing;
+                       # it is not meant for production packages.
+                       #
+                       unset( SKIP_EXTERNALS  CACHE )  # must remove so as not to trap user into a never ending failure
+                       unset( PACK_EXTERNALS  CACHE )
+                       message( FATAL_ERROR "ERROR: PACK_EXTERNALS can be set only if SKIP_EXTERNALS is unset (=0, or not supplied on command line)" )
+               endif()
+               set( need_ext 0 )
        endif()
-       set( need_ext 0 )
 endif()
 
 
@@ -243,30 +247,34 @@ unset( GPROF CACHE )                                      # we don't want this to persist
 
 # Include modules
 add_subdirectory( src/rmr/common )
-add_subdirectory( src/rmr/nng )
+if( BUILD_NNG )
+       add_subdirectory( src/rmr/nng )
+endif()
 add_subdirectory( src/rmr/si )
 add_subdirectory( doc )                                # this will auto skip if {X}fm is not available
 
 
 # shared and static libraries are built from the same object files.
-# librmr_nng is a combination of common and nng specific rmr functions.
+# librmr_* is a combination of common and * specific rmr functions.
 #
 
-add_library( rmr_nng_shared SHARED "$<TARGET_OBJECTS:nng_objects>;$<TARGET_OBJECTS:common_objects>" )
-set_target_properties( rmr_nng_shared
-       PROPERTIES
-       OUTPUT_NAME "rmr_nng"
-       SOVERSION ${major_version}
-       VERSION ${major_version}.${minor_version}.${patch_level} )
-
-# we only build/export the static archive (.a) if generating a dev package
-if( DEV_PKG )
-       add_library( rmr_nng_static STATIC "$<TARGET_OBJECTS:nng_objects>;$<TARGET_OBJECTS:common_objects>" )
-       set_target_properties( rmr_nng_static
+if( BUILD_NNG )
+       add_library( rmr_nng_shared SHARED "$<TARGET_OBJECTS:nng_objects>;$<TARGET_OBJECTS:common_objects>" )
+       set_target_properties( rmr_nng_shared
                PROPERTIES
                OUTPUT_NAME "rmr_nng"
                SOVERSION ${major_version}
                VERSION ${major_version}.${minor_version}.${patch_level} )
+
+       # we only build/export the static archive (.a) if generating a dev package
+       if( DEV_PKG )
+               add_library( rmr_nng_static STATIC "$<TARGET_OBJECTS:nng_objects>;$<TARGET_OBJECTS:common_objects>" )
+               set_target_properties( rmr_nng_static
+                       PROPERTIES
+                       OUTPUT_NAME "rmr_nng"
+                       SOVERSION ${major_version}
+                       VERSION ${major_version}.${minor_version}.${patch_level} )
+       endif()
 endif()
 
 add_library( rmr_si_shared SHARED "$<TARGET_OBJECTS:rmr_si_objects>;$<TARGET_OBJECTS:common_objects>" )
@@ -276,7 +284,7 @@ set_target_properties( rmr_si_shared
        SOVERSION ${major_version}
        VERSION ${major_version}.${minor_version}.${patch_level} )
 
-# even if not generating a development package we still need to generate the .a so that health check 
+# even if not generating a development package we still need to generate the .a so that health check
 # can link against it to avoid RPM install issues.
 #
 add_library( rmr_si_static STATIC "$<TARGET_OBJECTS:rmr_si_objects>;$<TARGET_OBJECTS:common_objects>" )
@@ -286,12 +294,14 @@ set_target_properties( rmr_si_static
        SOVERSION ${major_version}
        VERSION ${major_version}.${minor_version}.${patch_level} )
 
-# if externals need to be built, then we must force them to be built first by depending on them
-if( need_ext )
-       if( DEV_PKG )
-               add_dependencies( rmr_nng_shared;rmr_nng_static ext_nng )
-       else()
-               add_dependencies( rmr_nng_shared ext_nng )
+if( BUILD_NNG )
+       # if externals need to be built, then we must force them to be built first by depending on them
+       if( need_ext )
+               if( DEV_PKG )
+                       add_dependencies( rmr_nng_shared;rmr_nng_static ext_nng )
+               else()
+                       add_dependencies( rmr_nng_shared ext_nng )
+               endif()
        endif()
 endif()
 
@@ -319,32 +329,43 @@ add_subdirectory( src/support )
 # ------------- packaging -----------------------------------------------------
 
 #
-if( APPLE  )
-       message( "### apple hack: forcing hard coded library paths for nng/nano dynamic libraries" )
-       target_link_libraries( rmr_nng_shared ${CMAKE_CURRENT_BINARY_DIR}/lib/libnng${nng_so_suffix} )
+if( BUILD_NNG )
+       if( APPLE  )
+               message( "### apple hack: forcing hard coded library paths for nng/nano dynamic libraries" )
+               target_link_libraries( rmr_nng_shared ${CMAKE_CURRENT_BINARY_DIR}/lib/libnng${nng_so_suffix} )
+       endif()
 endif()
 
 # Define what should be installed, and where they should go. For dev package we install
 # only the RMr headers, man pages and archive (.a) files.  The run-time package gets just
 # the library (.so) files and nothing more.
 #
-if( DEV_PKG )
-       set( target_list "rmr_nng_static;rmr_si_static" )
+if( BUILD_NNG )
+       if( DEV_PKG )
+               set( target_list "rmr_nng_static;rmr_si_static" )
+       else()
+               set( target_list "rmr_nng_shared;rmr_si_shared" )
+       endif()
 else()
-       set( target_list "rmr_nng_shared;rmr_si_shared" )
+       if( DEV_PKG )
+               set( target_list "rmr_si_static" )
+       else()
+               set( target_list "rmr_si_shared" )
+       endif()
 endif()
 
 install( TARGETS ${target_list} EXPORT LibraryConfig
-       LIBRARY  DESTINATION ${install_lib}
-       ARCHIVE  DESTINATION ${install_lib}
-       PUBLIC_HEADER DESTINATION ${install_inc}
+       LIBRARY  DESTINATION ${install_lib}
+       ARCHIVE  DESTINATION ${install_lib}
+       PUBLIC_HEADER DESTINATION ${install_inc}
 )
 
 
 unset( DEV_PKG  CACHE )                        # prevent from being a hidden setting if user redoes things
 
 # install any nano/nng libraries in to the deb as well, but ONLY if asked for on the 'cmake ..' command
-# (sure would be nice if FILEs allowed for globbing; sadly it does not.)
+# (sure would be nice if FILEs allowed for globbing; sadly it does not.) Disabled by default if BUILD_NNG
+# is turned off.
 #
 if( PACK_EXTERNALS )
        message( "+++ including nano and nng libraries in the deb" )
index 03b212b..d28fe42 100644 (file)
 
 
 
-/* 
+/*
        Header  file defining  message types for various RMR messages
 */
 
 #define RIC_UNDEFINED                          -1
 
-/* 
+/*
 ---------------------------------------------------------
        RMR Reserved types
                All message types 0 - 99 are reserved for RMM.
 ---------------------------------------------------------
 */
-               
+
 #define RMRRM_TABLE_DATA                       20              // table data from route manger
 #define        RMRRM_REQ_TABLE                         21              // request for table update to route mangager
 #define RMRRM_TABLE_STATE                      22              // state of table to route mgr
 #define DC_ADM_GET_POLICY                      20002
 #define DC_ADM_GET_POLICY_ACK          20003
 
-#define A1_POLICY_REQ                          20010
-#define A1_POLICY_RESP                         20011
+#define A1_POLICY_REQ                          20010
+#define A1_POLICY_RESP                         20011
 #define A1_POLICY_QUERY                                20012
 
 
 // --- application specific message numbers 30000 - 39999
-    
+
 #define TS_UE_LIST                                     30000           // traffic steering
 #define TS_QOE_PRED_REQ                                30001
 #define TS_QUE_PREDICTION                      30002
 
 #define MC_REPORT                                      30010           // Measurement campaign xApp reports
 
+#define        DCAPTERM_RTPM_RMR_MSGTYPE       33001
+#define        DCAPTERM_GEO_RMR_MSGTYPE        33002
+
+
 
 // ---- these are old (release 0) definitions and should not be used ------
 
index 5fdf064..03f9db0 100644 (file)
@@ -84,6 +84,9 @@ static void* rtc_file( void* vctx ) {
 
                read_static_rt( ctx, vlevel );                                          // seed the route table if one provided
 
+               if( ctx->shutdown != 0 ) {                                                      // allow for graceful termination and unit testing
+                       return NULL;
+               }
                sleep( 60 );
        }
 }
@@ -102,28 +105,103 @@ static int refresh_vlevel( int vfd ) {
        return vlevel;
 }
 
+/*
+       Rtc_parse_msg parses a single message from the route manager. We allow multiple, newline terminated,
+       records in each message; it is required that the last record in the message be complete (we do not
+       reconstruct records split over multiple messages).  For each record, we call the record parser
+       to parse and add the information to the table being built.
+
+       This function was broken from the main rtc() function in order to be able to unit test it. Without
+       this as a standalone funciton, it was impossible to simulate a message arriving on the RTC's private
+       context.
+
+       To reduce malloc/free cycles, we allocate a static work buffer and expand it when needed; in other
+       words, this is not thread safe but it shouldn't need to be.
+*/
+static void rtc_parse_msg( uta_ctx_t *ctx, uta_ctx_t* pvt_cx, rmr_mbuf_t* msg, int vlevel,  int* flags ) {
+       static  unsigned char* pbuf = NULL;
+       static  int pbuf_size = 0;
+
+       unsigned char* payload;
+       unsigned char* curr;
+       unsigned char* nextr;
+       int mlen;
+
+       payload = msg->payload;
+       mlen = msg->len;                                        // usable bytes in the payload
+
+       if( DEBUG > 1 || (vlevel > 0) ) rmr_vlog( RMR_VL_DEBUG, "rmr_rtc: received rt message type=%d len=%d\n", msg->mtype, (int) mlen );
+       switch( msg->mtype ) {
+               case RMRRM_TABLE_DATA:
+                       if( (*flags & RTCFL_HAVE_UPDATE) == 0 ) {
+                               *flags |= RTCFL_HAVE_UPDATE;
+                               rmr_vlog( RMR_VL_INFO, "message flow from route manager starts\n" );
+                       }
+
+                       if( pbuf_size <= mlen ) {
+                               if( pbuf ) {
+                                       free( pbuf );
+                               }
+                               if( mlen < 512 ) {
+                                       pbuf_size = 1024;
+                               } else {
+                                       pbuf_size = mlen * 2;
+                               }
+                               pbuf = (char *) malloc( sizeof( char ) * pbuf_size );
+                       }
+                       memcpy( pbuf, payload, mlen );
+                       pbuf[mlen] = 0;                                                                         // don't depend on sender making this a legit string
+                       if( vlevel > 1 ) {
+                               rmr_vlog_force( RMR_VL_DEBUG, "rmr_rtc: rt message: (%s)\n", pbuf );
+                       }
+
+                       curr = pbuf;
+                       while( curr ) {                                                                         // loop over each record in the buffer
+                               nextr = strchr( (char *) curr, '\n' );                  // allow multiple newline records, find end of current and mark
+
+                               if( nextr ) {
+                                       *(nextr++) = 0;
+                               }
+
+                               if( vlevel > 1 ) {
+                                       rmr_vlog_force( RMR_VL_DEBUG, "rmr_rtc: processing (%s)\n", curr );
+                               }
+                               parse_rt_rec( ctx, pvt_cx, curr, vlevel, msg );         // parse record and add to in progress table; ack using rts to msg
+
+                               curr = nextr;
+                       }
+
+                       msg->len = 0;                           // force back into the listen loop
+                       break;
+
+               default:
+                       rmr_vlog( RMR_VL_WARN, "rmr_rtc: invalid message type=%d len=%d\n", msg->mtype, (int) msg->len );
+                       break;
+       }
+}
+
 /*
        Route Table Collector
        A side thread which either attempts to connect and request a table
        from the Route Manager, or opens a port and listens for Route Manager
        to push table updates.
 
-       It may do other things along the way (latency measurements, alarms, 
+       It may do other things along the way (latency measurements, alarms,
        respond to RMR pings, etc.).
 
        The behaviour with respect to listening for Route Manager updates vs
        the initiation of the connection and sending a request depends on the
        value of the ENV_RTG_ADDR (RMR_RTG_SVC)  environment variable. If
        host:port, or IP:port, is given, then we assume that we make the connection
-       and send a request for the table (request mode).  If the variable is just 
-       a port, then we assume Route Manager will connect and push updates (original 
+       and send a request for the table (request mode).  If the variable is just
+       a port, then we assume Route Manager will connect and push updates (original
        method).
 
        If the variable is not defined, the default behaviour, in order to be
-       backwards compatable, depends on the presence of the ENV_CTL_PORT 
+       backwards compatable, depends on the presence of the ENV_CTL_PORT
        (RMR_CTL_PORT) variable (new with the support for requesting a table).
 
-       
+
        ENV_CTL_PORT    ENV_RTG_ADDR    Behaviour
        unset                   unset                   Open default CTL port (DEF_CTL_PORT) and
                                                                        wait for Rt Mgr to push tables
@@ -134,15 +212,15 @@ static int refresh_vlevel( int vfd ) {
                                                                        used is the value set by ENV_CTL_PORT.
 
        unset                   set                             As described above. The default control
-                                                                       port (DEF_CTL_PORT) is used. 
+                                                                       port (DEF_CTL_PORT) is used.
 
-       When we are running in request mode, then we will send the RMR message 
-       RMRRM_REFRESH to this address (wormhole) as a request for the route manager 
+       When we are running in request mode, then we will send the RMR message
+       RMRRM_REFRESH to this address (wormhole) as a request for the route manager
        to send a new table. We will attempt to connect and send requests until
        we have a table. Calls to rmr_ready() will report FALSE until a table is
        loaded _unless_ a seed table was given.
 
-       Route table information is expected to arrive on RMR messages with type 
+       Route table information is expected to arrive on RMR messages with type
        RMRRM_TABLE_DATA.  There is NOT a specific message type for each possible
        table record, so the payload is as it appears in the seed file or as
        delivered in old versions.  It may take several RMRRM_TABLE_DATA messages
@@ -163,22 +241,16 @@ static void* rtc( void* vctx ) {
        uta_ctx_t*      ctx;                                    // context user has -- where we pin the route table
        uta_ctx_t*      pvt_cx;                                 // private context for session with rtg
        rmr_mbuf_t*     msg = NULL;                             // message from rtg
-       char*   payload;                                        // payload in the message
-       size_t  mlen;
        char*   my_port;                                        // the port number that we will listen on (4561 has been the default for this)
        char*   rtg_addr;                                       // host:port address of route table generator (route manager)
        char*   daddr;                                          // duplicated rtg address string to parse/trash
        size_t  buf_size;                                       // nng needs var pointer not just size?
-       char*   nextr;                                          // pointer at next record in the message
-       char*   curr;                                           // current record
-       int     i;
+       int             i;
        long    blabber = 0;                            // time of last blabber so we don't flood if rtg goes bad
        int             cstate = -1;                            // connection state to rtg
        int             state;                                          // processing state of some nng function
        char*   tokens[128];
        char    wbuf[128];
-       char*   pbuf = NULL;
-       int             pbuf_size = 0;                          // number allocated in pbuf
        int             ntoks;
        int             vfd = -1;                                       // verbose file des if we have one
        int             vlevel = 0;                                     // how chatty we should be 0== no nattering allowed
@@ -201,14 +273,14 @@ static void* rtc( void* vctx ) {
                vlevel = refresh_vlevel( vfd );
        }
 
-       ctx->flags |= CFL_NO_RTACK;                     // don't ack when reading from a file
+       ctx->flags |= CFL_NO_RTACK;                             // don't ack when reading from a file
        read_static_rt( ctx, vlevel );                  // seed the route table if one provided
        ctx->flags &= ~CFL_NO_RTACK;
 
 
        my_port = getenv( ENV_CTL_PORT );                               // default port to listen on (likely 4561)
        if( my_port == NULL || ! *my_port ) {                   // if undefined, then go with default
-               my_port = DEF_CTL_PORT; 
+               my_port = DEF_CTL_PORT;
                daddr = DEF_CTL_PORT;                                           // backwards compat; if ctl port not hard defined, default is to listen
        } else {
                daddr = DEF_RTG_WK_ADDR;                                        // if ctl port is defined, then default changes to connecting to well known RM addr
@@ -235,7 +307,7 @@ static void* rtc( void* vctx ) {
                                flags |= RTCFL_HAVE_UPDATE;                                     // and signal not to try to request an update
                                my_port = tokens[1];
                        } else {
-                               // rtg_addr points at rt mgr address and my port set from env or default stands as is   
+                               // rtg_addr points at rt mgr address and my port set from env or default stands as is
                        }
                        break;
        }
@@ -278,62 +350,16 @@ static void* rtc( void* vctx ) {
                                        rt_epcounts( ctx->rtable, ctx->my_name );
                                }
                        }
+
+                       if( ctx->shutdown != 0 ) {
+                               break;                                                  // mostly for unit test, but allows a forced stop
+                       }
                }
 
                vlevel = refresh_vlevel( vfd );                 // ensure it's fresh when we get a message
 
                if( msg != NULL && msg->len > 0 ) {
-                       payload = msg->payload;
-                       mlen = msg->len;                                        // usable bytes in the payload
-
-                       if( DEBUG > 1 || (vlevel > 0) ) rmr_vlog( RMR_VL_DEBUG, "rmr_rtc: received rt message type=%d len=%d\n", msg->mtype, (int) mlen );
-                       switch( msg->mtype ) {
-                               case RMRRM_TABLE_DATA:
-                                       if( (flags & RTCFL_HAVE_UPDATE) == 0 ) {
-                                               flags |= RTCFL_HAVE_UPDATE;
-                                               rmr_vlog( RMR_VL_INFO, "message flow from route manager starts\n" );
-                                       }
-
-                                       if( pbuf_size <= mlen ) {
-                                               if( pbuf ) {
-                                                       free( pbuf );
-                                               }
-                                               if( mlen < 512 ) {
-                                                       pbuf_size = 512;
-                                               } else {
-                                                       pbuf_size = mlen * 2;
-                                               }
-                                               pbuf = (char *) malloc( sizeof( char ) * pbuf_size );
-                                       }
-                                       memcpy( pbuf, payload, mlen );
-                                       pbuf[mlen] = 0;                                                                         // don't depend on sender making this a legit string
-                                       if( vlevel > 1 ) {
-                                               rmr_vlog_force( RMR_VL_DEBUG, "rmr_rtc: rt message: (%s)\n", pbuf );
-                                       }
-
-                                       curr = pbuf;
-                                       while( curr ) {                                                         // loop over each record in the buffer
-                                               nextr = strchr( curr, '\n' );                   // allow multiple newline records, find end of current and mark
-
-                                               if( nextr ) {
-                                                       *(nextr++) = 0;
-                                               }
-
-                                               if( vlevel > 1 ) {
-                                                       rmr_vlog_force( RMR_VL_DEBUG, "rmr_rtc: processing (%s)\n", curr );
-                                               }
-                                               parse_rt_rec( ctx, pvt_cx, curr, vlevel, msg );         // parse record and add to in progress table; ack using rts to msg
-
-                                               curr = nextr;
-                                       }
-
-                                       msg->len = 0;                           // force back into the listen loop
-                                       break;
-
-                               default:
-                                       rmr_vlog( RMR_VL_WARN, "rmr_rtc: invalid message type=%d len=%d\n", msg->mtype, (int) msg->len );
-                                       break;
-                       }
+                       rtc_parse_msg( ctx, pvt_cx, msg, vlevel, &flags );
                }
 
                if( ctx->shutdown ) {           // mostly for testing, but allows user app to close us down if rmr_*() function sets this
@@ -346,7 +372,7 @@ static void* rtc( void* vctx ) {
 }
 
 #ifndef SI95_BUILD
-// this is nng specific inas much as we allow raw (non-RMR) messages 
+// this is nng specific inas much as we allow raw (non-RMR) messages
 
 /*
        NOTE:   This is the original rtc code when we supported "raw" nano/nng messages
@@ -404,7 +430,7 @@ static void* raw_rtc( void* vctx ) {
        size_t  buf_size;                                       // nng needs var pointer not just size?
        char*   nextr;                                          // pointer at next record in the message
        char*   curr;                                           // current record
-       int     i;
+       int             i;
        long    blabber = 0;                            // time of last blabber so we don't flood if rtg goes bad
        int             cstate = -1;                            // connection state to rtg
        int             state;                                          // processing state of some nng function
@@ -433,7 +459,7 @@ static void* raw_rtc( void* vctx ) {
        if( (eptr = getenv( ENV_VERBOSE_FILE )) != NULL ) {
                vfd = open( eptr, O_RDONLY );
                vlevel = refresh_vlevel( vfd );
-       }                
+       }
 
        read_static_rt( ctx, vlevel );                                          // seed the route table if one provided
 
@@ -474,7 +500,7 @@ static void* raw_rtc( void* vctx ) {
                        sleep( count_delay );
                        rt_epcounts( ctx->rtable, ctx->my_name );
                }
-               
+
                free( fport );                                  // parinoid free and return
                return NULL;
        }
index 2d422bb..fbbffaf 100644 (file)
@@ -234,7 +234,7 @@ static int mt_data_cb( void* vctx, int fd, char* buf, int buflen ) {
                        remain = 0;
                } else {
                        need = river->msg_size - river->ipt;                                            // bytes from transport we need to have complete message
-                       if( DEBUG ) rmr_vlog( RMR_VL_DEBUG, "data callback enough in the buffer size=%d need=%d remain=%d\n", river->msg_size, need, remain );
+                       if( DEBUG ) rmr_vlog( RMR_VL_DEBUG, "data callback enough in the buffer size=%d need=%d remain=%d flgs=%02x\n", river->msg_size, need, remain, river->flags );
                        if( (river->flags & RF_DROP) == 0  ) {
                                memcpy( &river->accum[river->ipt], buf+bidx, need );                            // grab just what is needed (might be more)
                                buf2mbuf( ctx, river->accum, river->nbytes, fd );                                       // build an RMR mbuf and queue
@@ -242,7 +242,7 @@ static int mt_data_cb( void* vctx, int fd, char* buf, int buflen ) {
                                river->accum = (char *) malloc( sizeof( char ) *  river->nbytes );      // fresh accumulator
                        } else {
                                if( !(river->flags & RF_NOTIFIED) ) {
-                                       rmr_vlog( RMR_VL_WARN, "message larger than max (%d) have arrived on fd %d\n", river->nbytes, fd );
+                                       rmr_vlog( RMR_VL_WARN, "message larger than allocated buffer (%d) arrived on fd %d\n", river->nbytes, fd );
                                        river->flags |= RF_NOTIFIED;
                                }
                        }
index d1b9f26..712275e 100644 (file)
@@ -419,6 +419,10 @@ extern rmr_mbuf_t* rmr_torcv_msg( void* vctx, rmr_mbuf_t* old_msg, int ms_to ) {
 }
 
 /*
+       DEPRECATED -- this function is not needed in the SI world, and when NNG goes away this will
+               too.  This function likely will not behave as expected in SI, and we are pretty sure it
+               isn't being used as there was an abort triggering reference to rmr_rcv() until now.
+
        This blocks until the message with the 'expect' ID is received. Messages which are received
        before the expected message are queued onto the message ring.  The function will return
        a nil message and set errno to ETIMEDOUT if allow2queue messages are received before the
@@ -455,22 +459,25 @@ extern rmr_mbuf_t* rmr_rcv_specific( void* vctx, rmr_mbuf_t* msg, char* expect,
        if( DEBUG ) rmr_vlog( RMR_VL_DEBUG, " rcv_specific waiting for id=%s\n",  expect );
 
        while( queued < allow2queue ) {
-               msg = rcv_msg( ctx, msg );                                      // hard wait for next
-               if( msg->state == RMR_OK ) {
-                       if( memcmp( msg->xaction, expect, exp_len ) == 0 ) {                    // got it -- return it
-                               if( DEBUG ) rmr_vlog( RMR_VL_DEBUG, " rcv-specific matched (%s); %d messages were queued\n", msg->xaction, queued );
-                               return msg;
-                       }
-
-                       if( ! uta_ring_insert( ctx->mring, msg ) ) {                                    // just queue, error if ring is full
-                               if( DEBUG > 1 ) rmr_vlog( RMR_VL_DEBUG, " rcv_specific ring is full\n" );
-                               errno = ENOBUFS;
-                               return NULL;
+               msg = rmr_rcv_msg( ctx, msg );                                  // hard wait for next
+               if( msg != NULL ) {
+                       if( DEBUG ) rmr_vlog( RMR_VL_DEBUG, " rcv_specific checking message; queued=%d allowed=%d state=%d\n",  queued, allow2queue, msg->state );
+                       if( msg->state == RMR_OK ) {
+                               if( memcmp( msg->xaction, expect, exp_len ) == 0 ) {                    // got it -- return it
+                                       if( DEBUG ) rmr_vlog( RMR_VL_DEBUG, " rcv_specific matched (%s); %d messages were queued\n", msg->xaction, queued );
+                                       return msg;
+                               }
+
+                               if( ! uta_ring_insert( ctx->mring, msg ) ) {                                    // just queue, error if ring is full
+                                       if( DEBUG > 1 ) rmr_vlog( RMR_VL_DEBUG, " rcv_specific ring is full\n" );
+                                       errno = ENOBUFS;
+                                       return NULL;
+                               }
+
+                               if( DEBUG ) rmr_vlog( RMR_VL_DEBUG, " rcv_specific queued message type=%d\n", msg->mtype );
+                               queued++;
+                               msg = NULL;
                        }
-
-                       if( DEBUG ) rmr_vlog( RMR_VL_DEBUG, " rcv_specific queued message type=%d\n", msg->mtype );
-                       queued++;
-                       msg = NULL;
                }
        }
 
@@ -1079,8 +1086,10 @@ extern rmr_mbuf_t* rmr_mt_call( void* vctx, rmr_mbuf_t* mbuf, int call_id, int m
 
        // must vet call_id here, all others vetted by workhorse mt_call() function
        if( call_id > MAX_CALL_ID || call_id < 2 ) {            // 0 and 1 are reserved; user app cannot supply them
-               mbuf->state = RMR_ERR_BADARG;
-               mbuf->tp_state = EINVAL;
+               if( mbuf != NULL ) {
+                       mbuf->state = RMR_ERR_BADARG;
+                       mbuf->tp_state = EINVAL;
+               }
                return mbuf;
        }
 
index e44b2bb..22dff3a 100644 (file)
 CC = gcc
 coverage_opts = -ftest-coverage -fprofile-arcs
 
-libs = -lnng -lpthread -lm
+libs = -lpthread -lm
 ipaths = -I ../src/rmr/common/src/ -I ../src/rmr/common/include  \
-       -I ../src/rmr/nng/include/ -I ../src/rmr/nng/src/  \
-       -I ../src/rmr/nanomsg/include/ -I ../src/rmr/nanomsg/src/  \
        -I ../src/rmr/si/include -I ../src/rmr/si/src -I ../src/rmr/si/si95
 
 #sa_tests = sa_tools_test.o
index 528e9cc..b7f97bf 100644 (file)
@@ -96,8 +96,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 "  );
        }
@@ -112,7 +112,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 ) {
@@ -210,9 +210,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
                }
@@ -257,6 +256,13 @@ static int rmr_api_test( ) {
        rmr_close( rmc );                       // no return to check; drive for coverage
 
 
+       // --------------- nil pointer exception checks
+       rmr_rcv_specific( NULL, NULL, "foo", 0 );
+       rmr_mt_rcv( NULL, NULL, 0 );
+       mt_call( NULL, NULL, 0, 1, NULL );
+       rmr_mt_call( NULL, NULL, 0, 1 );
+       rmr_set_low_latency( NULL );
+       rmr_set_fack( NULL );
 
        // --------------- phew, done ------------------------------------------------------------------------------
 
index ad543a0..57313f8 100644 (file)
@@ -150,6 +150,7 @@ static int rmr_rcv_test( ) {
        }
 
        rmr_rts_msg( NULL, NULL );                      // drive for coverage
+       errors += fail_if( errno == 0, "rmr_rts_msg did not set errno when given a nil context "  );
        rmr_rts_msg( rmc, NULL );
        errors += fail_if( errno == 0, "rmr_rts_msg did not set errno when given a nil message "  );
 
@@ -225,6 +226,42 @@ static int rmr_rcv_test( ) {
        rmr_close( rmc );                       // no return to check; drive for coverage
 
 
+       // ------- receive specific is deprecated, but we still test to keep sonar happy ---------------
+
+       rmr_rcv_specific( NULL, NULL, "12345", 0 );             // drive for error handling coverage
+       rmr_rcv_specific( NULL, msg, "12345", 2 );
+
+       strncpy( wbuf, "dummy message", sizeof( wbuf ) );
+       msg = mk_populated_msg( 1024, 0, 0, -1, strlen( wbuf ) + 1 );
+       strncpy( msg->payload, wbuf, msg->len );
+       msg = rmr_send_msg( rmc, msg );                                         // give specific something to chew on
+
+       strncpy( msg->payload, wbuf, msg->len );
+       msg->mtype = 0;
+       rmr_str2xact( msg, "12345" );                                           // should allow rcv to find it
+       msg = rmr_send_msg( rmc, msg );
+
+       msg = rmr_rcv_specific( rmc, NULL, "12345", 2 );
+       if( msg ) {
+               errors += fail_if( msg->state != 0, "rmr_rcv_specific failed to find the expected message" );
+       } else {
+               errors++;
+               fprintf( stderr, "<FAIL> rcv specific expected to return a message and did not\n" );
+       }
+
+       strncpy( wbuf, "dummy message", sizeof( wbuf ) );
+       msg = mk_populated_msg( 1024, 0, 0, -1, strlen( wbuf ) + 1 );
+       strncpy( msg->payload, wbuf, msg->len );
+       msg = rmr_send_msg( rmc, msg );                                         // give specific something to chew on
+
+       fprintf( stderr, "<INFO> starting rmr_rcv_specific test for no expected message\n" );
+       strncpy( msg->payload, wbuf, msg->len );
+       msg->mtype = 0;
+       rmr_str2xact( msg, "72345" );                                           // rcv should not find it
+       msg = rmr_send_msg( rmc, msg );
+       msg = rmr_rcv_specific( rmc, msg, "12345", 2 );
+       fail_if_nil( msg, "rmr_rcv_specific expected to retun nil message did  not" );
+
        // --------------- phew, done ------------------------------------------------------------------------------
 
        if( ! errors ) {
index d87a743..dbe8d78 100644 (file)
@@ -98,6 +98,7 @@ fprintf( stderr, "<INFO> build key: %x %x --> %llx\n", (int) mtype, (int) sid, (
 */
 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
@@ -521,6 +522,36 @@ static int rt_test( ) {
                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( 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
index c77f389..fd6dd56 100644 (file)
@@ -21,7 +21,7 @@
 /*
        Mmemonic:       si95_test.c
        Abstract:       This is the main driver to test the si95 core functions
-                               (within rmr/src/si/src/si95). 
+                               (within rmr/src/si/src/si95).
 
        Author:         E. Scott Daniels
        Date:           6 March 2018
@@ -58,7 +58,7 @@
 #define DEBUG 1
 
                                                                                        // specific test tools in this directory
-#undef NNG_UNDER_TEST                                          // NNG is NOT under test so undefine if set
+#undef NNG_UNDER_TEST                                          // NNG is NOT under test so undefine if set
 #define NO_EMULATION 1                                         // no emulation of transport functions
 #define NO_PRIVATE_HEADERS 1                           // no rmr_si or rmr_nng headers
 #define NO_DUMMY_RMR 1                                         // no msg things
@@ -127,7 +127,7 @@ static int memory( ) {
                ((struct tp_blk *)ptr)->squeue = iptr;
                SItrash(  TP_BLK, ptr );
        }
-       
+
        ptr = SInew( GI_BLK );
        errors += fail_if_nil( ptr, "memory: sinew returned nil when given giblk request" );
        SItrash(  GI_BLK, ptr );                // GI block cannot be trashed, ensure this (valgind will complain about a leak)
@@ -155,7 +155,7 @@ static int init() {
 
 static int cleanup() {
        int errors = 0;
-       
+
        if( ! si_ctx ) {
                return 0;
        }
@@ -163,8 +163,9 @@ static int cleanup() {
        SItp_stats( si_ctx );           // drive for coverage only
        SItp_stats( NULL );
 
-       SIconnect( si_ctx, "localhost:43086" );         // ensure context has a tp block to free on shutdown
-       SIshutdown( si_ctx );
+       SIconnect( si_ctx, "localhost:43086" ); // ensure context has a tp block to free on shutdown
+       SIshutdown( NULL );
+       SIabort( si_ctx );
 
 
        fprintf( stderr, "<INFO> cleanup  module finished with %d errors\n", errors );
@@ -194,9 +195,8 @@ static int addr() {
        l = SIaddress( buf1, (void **)  &dest, AC_TOADDR6 );
        errors += fail_if_true( l > 0, "to addr6 with bad addr convdersion returned valid len" );
 
-       snprintf( buf1, sizeof( buf1 ), "[ff02::5]:4002" );             // v6 might not be supported so failure is OK here
+       snprintf( buf1, sizeof( buf1 ), "[ff02::5]:4002" );             // v6 might not be supported so failure is OK here; driving for coverage
        l=SIaddress( buf1, (void **) &dest, AC_TOADDR6 );
-       errors += fail_if_true( l < 1, "to addr convdersion failed" );
 
        snprintf( buf1, sizeof( buf1 ), "localhost:43086" );
        l = SIaddress( buf1, (void **) &dest, AC_TOADDR );
@@ -222,11 +222,11 @@ static int conn( ) {
        state = SIconnect( si_ctx, "localhost:4567" );          // driver regular connect
        errors += fail_if_true( state < 0, "connect to low port failed" );
 
-       state = SIconnect( si_ctx, "localhost:43086" );         // drive save connect with good return code
+       state = SIconnect( si_ctx, "localhost:43086" );         // drive save connect with good return code
        errors += fail_if_true( state < 0, "connect to high port failed" );
 
        tpem_set_addr_dup_state( 1 );                           // force get sockket name emulation to return a duplicate address
-       state = SIconnect( si_ctx, "localhost:43086" );         // drive save connect with good return code
+       state = SIconnect( si_ctx, "localhost:43086" );         // drive save connect with good return code
        errors += fail_if_true( state >= 0, "forced dup connect did not return error" );
 
        tpem_set_addr_dup_state( 0 );                           // force get sockket name emulation to return a duplicate address
index 5768f3e..9efba71 100644 (file)
@@ -41,7 +41,7 @@
 #include "rmr_agnostic.h"
 
 // ----------- local test support ----------------------------------------------------------
-#define CLONE  1                       // convenience constants for payload realloc tests
+#define CLONE  1                       // convenience constants for payload realloc tests
 #define NO_CLONE 0
 #define COPY 1
 #define NO_COPY 0
        have been included by the test module(s) which include this.
 */
 static int sr_si_test() {
-       uta_ctx_t* ctx;                 // context needed to test load static rt
+       uta_ctx_t* ctx;                 // two context structs needed to test route table collector
+       uta_ctx_t* pctx;
        uta_ctx_t*      real_ctx;       // real one to force odd situations for error testing
        int errors = 0;                 // number errors found
        rmr_mbuf_t*     mbuf;           // mbuf to send/receive
        rmr_mbuf_t*     mb2;            // second mbuf when needed
        int             whid = -1;
        int             last_whid;
-       int     state;
-       int     nn_dummy_sock;                                  // dummy needed to drive send
+       int             state;
+       int             nn_dummy_sock;                                  // dummy needed to drive send
        int             size;
        int             i;
+       int             flags = 0;                                              // flags needed to pass to rtc funcitons
        void*   p;
        char*   payload_str;
 
        ctx = mk_dummy_ctx();                                                                   // in the si world we need some rings in the context
+       pctx = mk_dummy_ctx();
 
        ctx->max_plen = RMR_MAX_RCV_BYTES + sizeof( uta_mhdr_t );
        ctx->max_mlen = ctx->max_plen + sizeof( uta_mhdr_t );
@@ -114,8 +117,7 @@ static int sr_si_test() {
        if( mbuf ) {
                errors += fail_not_equal( mbuf->state, RMR_ERR_BADARG, "send with buffer but nil context didn't return right state" );
        } else {
-               //mbuf = rmr_rcv_msg( ctx, NULL );
-mbuf = rmr_alloc_msg( ctx, 2048 );
+               mbuf = rmr_alloc_msg( ctx, 2048 );
        }
 
        //size = 2048 - em_hdr_size();          // emulated receive allocates 2K buffers -- subtract off header size
@@ -126,7 +128,12 @@ mbuf = rmr_alloc_msg( ctx, 2048 );
        rmr_free_msg( mbuf );
 
 
-       // ---- drive rtc in a 'static' (not pthreaded) mode to get some coverage; no 'results' to be verified -----
+       // -------- drive rtc in a 'static' (not pthreaded) mode to get some coverage; no 'results' to be verified -----
+       /*
+               It is impossible to drive the message loop of the rtc from a unit test because
+               we cannot generate a message that will arrive on its private RMR context.
+       */
+
        setenv( ENV_RTG_RAW, "0", 1 );                                                          // rtc is never raw under SI
        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, 0654 );
@@ -136,7 +143,10 @@ mbuf = rmr_alloc_msg( ctx, 2048 );
        }
        ctx->shutdown = 1;                      // should force rtc to quit on first pass
        rtc( NULL );                            // coverage test with nil pointer
-/*
+
+       rtc_file( NULL );                       // the static file only collector
+       rtc_file( ctx );
+
        rtc( ctx );
 
        setenv( "RMR_RTG_SVC", "4567", 1 );             // drive for edge case coverage to ensure no nil pointer etc
@@ -145,7 +155,17 @@ mbuf = rmr_alloc_msg( ctx, 2048 );
        rtc( ctx );
        setenv( "RMR_RTG_SVC", "tcp:4567:error", 1 );
        rtc( ctx );
-*/
+       setenv( "RMR_RTG_SVC", "localhost:4589", 1 );           // should force a request to be sent though no reponse back.
+       rtc( ctx );
+
+       payload_str = "newrt|start|abc-def\nmse|10|-1|host1:43086\nmse|20|-1|host1:43086\nnewrt|end|2\n";
+       mbuf = mk_populated_msg( 1024, 0, 20, -2, strlen( payload_str ) );
+       memcpy( mbuf->payload, payload_str, mbuf->len );
+       rtc_parse_msg( ctx, pctx, mbuf, 5, &flags );
+
+       mbuf = mk_populated_msg( 1024, 0, 90, -2, strlen( payload_str ) );              // drive with invalid message type for coverage
+       rtc_parse_msg( ctx, pctx, mbuf, 5, &flags );
+
 
        // ------------- reallocation tests ------------------------------------------------------------
        // we use mk_populated_msg() to create a message with mid/sid/plen pushed into the transport
index 277f741..2a66c04 100644 (file)
@@ -63,10 +63,12 @@ static inline uta_ctx_t *mk_dummy_ctx() {
        }
 
        memset( ctx, 0, sizeof( *ctx ) );
-       
+
        ctx->mring = uta_mk_ring( 4096 );                               // message ring is always on for si
        ctx->zcb_mring = uta_mk_ring( 128 );            // zero copy buffer mbuf ring to reduce malloc/free calls
        ctx->si_ctx = malloc( 1024 );
+       ctx->my_name = strdup( "hostname1" );
+       ctx->my_ip = strdup( "123.45.67.89" );
 
        return ctx;
 }
index ad21465..718055a 100755 (executable)
@@ -190,7 +190,7 @@ function discount_an_checks {
                }
        }
 
-       /-:/ {                          # skip unexecutable lines
+       /-:/ {                          # skip unexecutable lines
                spit_line()
                seq++                                   # allow blank lines in a sequence group
                next
@@ -345,7 +345,8 @@ show_output=0                                                                       # show output from each test execution (-S)
 quiet=0
 gen_xml=0
 replace_flags=1                                                                        # replace ##### in gcov for discounted lines
-run_nano_tests=0
+run_nano_tests=0                                                               # can nolonger be turned on
+run_nng_tests=0                                                                        # -N will enable
 always_gcov=0                                                                  # -a sets to always run gcov even if failure
 save_gcov=1                                                                            # -o turns this off
 out_dir=${UT_COVERAGE_DIR:-/tmp/rmr_gcov}              # -O changes output directory
@@ -360,7 +361,7 @@ do
                -C)     builder="$2"; shift;;           # custom build command
                -G)     builder="gmake %s";;
                -M)     builder="mk -a %s";;            # use plan-9 mk (better, but sadly not widly used)
-               -N)     run_nano_tests=1;;
+               -N)     run_nng_tests=1;;
                -O)     out_dir=$2; shift;;
 
                -a)     always_gcov=1;;
@@ -385,9 +386,9 @@ do
                        ;;
 
 
-               -h)     usage; exit 0;;
+               -h)             usage; exit 0;;
                --help) usage; exit 0;;
-               -\?)    usage; exit 0;;
+               -\?)    usage; exit 0;;
 
                *)      echo "unrecognised option: $1" >&2
                        usage >&2
@@ -399,7 +400,7 @@ do
 done
 
 
-if (( strict ))                # if in strict mode, coverage shortcomings are failures
+if (( strict ))                        # if in strict mode, coverage shortcomings are failures
 then
        cfail="FAIL"
 else
@@ -418,11 +419,16 @@ then
        do
                if [[ $tfile != *"static_test.c" ]]
                then
-                       if(( ! run_nano_tests )) && [[ $tfile == *"nano"* ]]
+                       if (( ! run_nng_tests )) && [[ $tfile == *"nng"* ]]             # drop any nng file unless -N given
+                       then
+                               continue
+                       fi
+                       if [[ $tfile == *"nano"* ]]                     # no longer support nano tests; drop regardless
                        then
                                continue
                        fi
 
+                       echo "<INFO> add test: $tfile" >&2
                        flist="${flist}$tfile "
                fi
        done
@@ -445,6 +451,11 @@ rm -fr *.gcov                      # ditch the previous coverage files
 ut_errors=0                    # unit test errors (not coverage errors)
 errors=0
 
+if ! touch /tmp/PPID$$.noise
+then
+       echo "<ERR> unable to write to /tmp???"
+fi
+
 for tfile in $flist
 do
        for x in *.gcov
@@ -455,14 +466,14 @@ do
                fi
        done
 
+       echo "$tfile --------------------------------------"
        (       # all noise is now captured into a tmp file to support quiet mode
-               echo "$tfile --------------------------------------"
                bcmd=$( printf "$builder" "${tfile%.c}" )
                if ! $bcmd >/tmp/PID$$.log 2>&1
                then
                        echo "[FAIL] cannot build $tfile"
                        cat /tmp/PID$$.log
-                       rm -f /tmp/PID$$
+                       # do NOT remove tmp files; bash seens to not gen a new PID for subshells
                        exit 1
                fi
 
@@ -612,7 +623,6 @@ do
                                                }
                                        }
                                }
-
                        }
 
                        END {
@@ -623,7 +633,7 @@ do
                rc=$?
                cat /tmp/PID$$.log
 
-               if (( rc  || force_discounting ))       # didn't pass, or forcing, see if discounting helps
+               if (( rc  || force_discounting ))       # didn't pass, or forcing, see if discounting helps
                then
                        if (( ! verbose ))
                        then
@@ -645,7 +655,7 @@ do
 
                                tail -1 /tmp/PID$$.disc | grep '\['
 
-                               if (( verbose > 1 ))                    # updated file was generated, keep here
+                               if (( verbose > 1 ))                    # updated file was generated, keep here
                                then
                                        echo "[INFO] discounted coverage info in: ${tfile##*/}.dcov"
                                fi
@@ -653,7 +663,7 @@ do
                                mv /tmp/PID$$.disc ${name##*/}.dcov
                        done
                fi
-       )>/tmp/PID$$.noise 2>&1
+       )>/tmp/PID$$.noise 2>&1
        if (( $? != 0 ))
        then
                (( ut_errors++ ))
@@ -685,7 +695,7 @@ do
        if [[ $xx != *"test"* ]]
        then
                of=${xx%.gcov}.dcov
-               discount_an_checks $xx  >$of
+               discount_an_checks $xx  >$of
                if [[ -n $of ]]
                then
                        tail -1 $of |  grep '\['