Remove NNG libraries from packages
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
diff --git a/CHANGES_CORE.txt b/CHANGES_CORE.txt
index 89d0595..481452c 100644
--- a/CHANGES_CORE.txt
+++ b/CHANGES_CORE.txt
@@ -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)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3109513..a8aa1ba 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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 @@
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 @@
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 @@
# 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 @@
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 @@
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 @@
# ------------- 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" )
diff --git a/src/rmr/common/include/RIC_message_types.h b/src/rmr/common/include/RIC_message_types.h
index 03b212b..d28fe42 100644
--- a/src/rmr/common/include/RIC_message_types.h
+++ b/src/rmr/common/include/RIC_message_types.h
@@ -20,19 +20,19 @@
-/*
+/*
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
@@ -147,19 +147,23 @@
#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 ------
diff --git a/src/rmr/common/src/rtc_static.c b/src/rmr/common/src/rtc_static.c
index 5fdf064..03f9db0 100644
--- a/src/rmr/common/src/rtc_static.c
+++ b/src/rmr/common/src/rtc_static.c
@@ -84,6 +84,9 @@
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 );
}
}
@@ -103,27 +106,102 @@
}
/*
+ 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
#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 @@
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 @@
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 @@
sleep( count_delay );
rt_epcounts( ctx->rtable, ctx->my_name );
}
-
+
free( fport ); // parinoid free and return
return NULL;
}
diff --git a/src/rmr/si/src/mt_call_si_static.c b/src/rmr/si/src/mt_call_si_static.c
index 2d422bb..fbbffaf 100644
--- a/src/rmr/si/src/mt_call_si_static.c
+++ b/src/rmr/si/src/mt_call_si_static.c
@@ -234,7 +234,7 @@
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 @@
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;
}
}
diff --git a/src/rmr/si/src/rmr_si.c b/src/rmr/si/src/rmr_si.c
index d1b9f26..712275e 100644
--- a/src/rmr/si/src/rmr_si.c
+++ b/src/rmr/si/src/rmr_si.c
@@ -419,6 +419,10 @@
}
/*
+ 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 @@
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;
- }
+ 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( ! 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 @@
// 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;
}
diff --git a/test/Makefile b/test/Makefile
index e44b2bb..22dff3a 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -22,10 +22,8 @@
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
diff --git a/test/rmr_si_api_static_test.c b/test/rmr_si_api_static_test.c
index 528e9cc..b7f97bf 100644
--- a/test/rmr_si_api_static_test.c
+++ b/test/rmr_si_api_static_test.c
@@ -96,8 +96,8 @@
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 @@
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 @@
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 @@
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 ------------------------------------------------------------------------------
diff --git a/test/rmr_si_rcv_static_test.c b/test/rmr_si_rcv_static_test.c
index ad543a0..57313f8 100644
--- a/test/rmr_si_rcv_static_test.c
+++ b/test/rmr_si_rcv_static_test.c
@@ -150,6 +150,7 @@
}
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 @@
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 ) {
diff --git a/test/rt_static_test.c b/test/rt_static_test.c
index d87a743..dbe8d78 100644
--- a/test/rt_static_test.c
+++ b/test/rt_static_test.c
@@ -98,6 +98,7 @@
*/
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 @@
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
diff --git a/test/si95_test.c b/test/si95_test.c
index c77f389..fd6dd56 100644
--- a/test/si95_test.c
+++ b/test/si95_test.c
@@ -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 @@
((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 cleanup() {
int errors = 0;
-
+
if( ! si_ctx ) {
return 0;
}
@@ -163,8 +163,9 @@
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 @@
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 @@
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
diff --git a/test/sr_si_static_test.c b/test/sr_si_static_test.c
index 5768f3e..9efba71 100644
--- a/test/sr_si_static_test.c
+++ b/test/sr_si_static_test.c
@@ -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
@@ -59,21 +59,24 @@
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 @@
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 @@
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 @@
}
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 @@
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
diff --git a/test/test_ctx_support.c b/test/test_ctx_support.c
index 277f741..2a66c04 100644
--- a/test/test_ctx_support.c
+++ b/test/test_ctx_support.c
@@ -63,10 +63,12 @@
}
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;
}
diff --git a/test/unit_test.ksh b/test/unit_test.ksh
index ad21465..718055a 100755
--- a/test/unit_test.ksh
+++ b/test/unit_test.ksh
@@ -190,7 +190,7 @@
}
}
- /-:/ { # skip unexecutable lines
+ /-:/ { # skip unexecutable lines
spit_line()
seq++ # allow blank lines in a sequence group
next
@@ -345,7 +345,8 @@
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 @@
-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 @@
;;
- -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 @@
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 @@
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 @@
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 @@
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 @@
}
}
}
-
}
END {
@@ -623,7 +633,7 @@
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 @@
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 @@
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 @@
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 '\['