feat(API):  Add trace data functions

The trace data in the RMr header can now be set and
retrieved by the user programme with the new functions.

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

 Finish trace functions for nng

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

 Switch to address macro from offset

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

Set version manually

The CI process _should_ set a tag when the code is merged
and we will pull that tag and use it as the maj.min.patch
version.  However, the CI process is not doing this, so
we are forced to mantain the version number in the CMake
file for now.  This commit sets that version to 1.0.17.

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

 Add trace functions for nanomsg

Change-Id: If640b7ee8a4996d8c324bbdd2cb4a85f68a3cc73
Signed-off-by: E. Scott Daniels <daniels@research.att.com>
diff --git a/test/mbuf_api_static_test.c b/test/mbuf_api_static_test.c
index 4c0cd5e..8598136 100644
--- a/test/mbuf_api_static_test.c
+++ b/test/mbuf_api_static_test.c
@@ -42,6 +42,7 @@
 int mbuf_api_test( ) {
 	unsigned char* c;
 	int i;
+	int state;
 	int errors = 0;
 	rmr_mbuf_t*	mbuf;
 	unsigned char src_buf[256];
@@ -57,6 +58,7 @@
 	mbuf->header = mbuf->payload;
 	mbuf->alloc_len = 1024;
 
+	// --- test payload field  access functions ---------------------------------------------------
 	memset( src_buf, 0, sizeof( src_buf ) );
 	rmr_bytes2payload( mbuf, NULL, strlen( src_buf) );				// errno should be set on return
 	errors += fail_if( errno == 0, "buf copy to payload with nil src returned good errno" );
@@ -76,6 +78,8 @@
 	snprintf( src_buf, sizeof( src_buf ), "This is some text in the buffer" );
 	rmr_str2payload( mbuf, src_buf );							// this uses bytes2payload, so only one invocation needed
 
+
+	// --- test meid field  access functions ---------------------------------------------------
 	errno = 0;
 	i = rmr_bytes2meid( NULL, src_buf, RMR_MAX_MEID );
 	errors += fail_if( errno == 0, "(errno) attempt to copy bytes to meid with nil message" );
@@ -121,6 +125,24 @@
 	errors += fail_if( i == RMR_OK, "(rv) attempt to copy string to meid with large source buffer" );
 
 
+	snprintf( src_buf, sizeof( src_buf ), "test-meid" );
+	rmr_str2meid( mbuf, src_buf );
+
+	errno = 0;
+	c = rmr_get_meid( NULL, NULL );
+	errors += fail_if( c != NULL, "get meid with nil message buffer" );
+	errors += fail_if( errno == 0, "(errno bad) get meid with nil msg buffer" ); 
+	
+	c = rmr_get_meid( mbuf, NULL );			// should allocate and return c
+	errors += fail_if( c == NULL, "get meid with nil dest pointer (did not allocate a buffer)" );
+	errors += fail_if( strcmp( c, "test-meid" ) != 0, "did not get expected meid from mbuffer" );
+
+	c = rmr_get_meid( mbuf, c );
+	errors += fail_if( c == NULL, "get meid with a dest pointer returned no pointer" );
+	errors += fail_if( strcmp( c, "test-meid" ) != 0, "did not get expected meid from mbuffer" );
+
+
+	// --- test transaction field  access functions ---------------------------------------------------
 	errno = 0;
 	i = rmr_bytes2xact( NULL, src_buf, RMR_MAX_XID );
 	errors += fail_if( errno == 0, "(errno) attempt to copy bytes to xact with nil message" );
@@ -165,23 +187,67 @@
 	errors += fail_if( errno == 0, "(errno) attempt to copy string to xact with large source buffer" );
 	errors += fail_if( i == RMR_OK, "(rv) attempt to copy string to xact with large source buffer" );
 
-	
-	snprintf( src_buf, sizeof( src_buf ), "test-meid" );
-	rmr_str2meid( mbuf, src_buf );
 
-	errno = 0;
-	c = rmr_get_meid( NULL, NULL );
-	errors += fail_if( c != NULL, "get meid with nil message buffer" );
-	errors += fail_if( errno == 0, "(errno bad) get meid with nil msg buffer" ); 
+
+	// ------------ trace data tests ----------------------------------------------------------------
+	// CAUTION: to support standalone mbuf api tests, the underlying buffer reallocation functions are NOT used
+	//			if this is driven by the mbuf_api_test.c driver
+
+	mbuf = test_mk_msg( 2048, 0 );		// initially no trace size to force realloc
+
+	state = TRACE_OFFSET( mbuf->header ) - PAYLOAD_OFFSET( mbuf->header );		// no trace data, payload and trace offset should be the same
+	errors += fail_not_equal( state, 0, "trace offset and payload offset do NOT match when trace data is absent" );
+
+	state = rmr_get_trlen( mbuf );
+	errors += fail_not_equal( state, 0, "initial trace len reported (a) does not match expected (b)" );
+
+	state = rmr_set_trace( NULL, src_buf, 100 );				// coverage test on nil check
+	errors += fail_not_equal( state, 0, "set trace with nil msg didn't return expected 0 status" );
+
+	state = rmr_set_trace( mbuf, src_buf, 0 );				// coverage test on length check
+	errors += fail_not_equal( state, 0, "set trace with 0 len didn't return expected 0 status" );
+
+	state = rmr_get_trace( NULL, src_buf, 100 );				// coverage test on nil check
+	errors += fail_not_equal( state, 0, "get trace with nil msg didn't return expected 0 status" );
+
+	state = rmr_get_trace( mbuf, NULL, 100 );					// coverage test on nil check
+	errors += fail_not_equal( state, 0, "get trace with nil dest didn't return expected 0 status" );
+
+	state = rmr_get_trlen( NULL );								// coverage test on nil check
+	errors += fail_not_equal( state, 0, "get trace length with nil msg didn't return expected 0 status" );
 
 	
-	c = rmr_get_meid( mbuf, NULL );			// should allocate and return c
-	errors += fail_if( c == NULL, "get meid with nil dest pointer (did not allocate a buffer)" );
-	errors += fail_if( strcmp( c, "test-meid" ) != 0, "did not get expected meid from mbuffer" );
+	src_buf[0] = 0;
+	state = rmr_set_trace( mbuf, "foo bar was here", 17 );		// should force a realloc
+	errors += fail_not_equal( state, 17, "bytes copied to trace (a) did not match expected size (b)" );
 
-	c = rmr_get_meid( mbuf, c );
-	errors += fail_if( c == NULL, "get meid with a dest pointer returned no pointer" );
-	errors += fail_if( strcmp( c, "test-meid" ) != 0, "did not get expected meid from mbuffer" );
+	state = rmr_get_trace( mbuf, src_buf, 17 );
+	errors += fail_not_equal( state, 17, "bytes retrieved from trace (a) did not match expected size (b)" );
+
+	state = rmr_get_trlen( mbuf );
+	errors += fail_not_equal( state, 17, "trace len reported (a) does not match expected (b)" );
+	state = strcmp( src_buf, "foo bar was here" );
+	errors+= fail_not_equal( state, 0, "compare of pulled trace info did not match" );
+
+	state = TRACE_OFFSET( mbuf->header ) - PAYLOAD_OFFSET( mbuf->header );		// when there is a trace area these should NOT be the same
+	errors += fail_if_equal( state, 0, "trace offset and payload offset match when trace data is present" );
+
+
+											// second round of trace testing, allocating a message with a trace size that matches
+	mbuf = test_mk_msg( 2048, 17 );			// trace size that matches what we'll stuff in, no realloc
+	state = rmr_get_trlen( mbuf );
+	errors += fail_not_equal( state, 17, "alloc with trace size: initial trace len reported (a) does not match expected (b)" );
+
+	src_buf[0] = 0;
+	state = rmr_set_trace( mbuf, "foo bar was here", 17 );		// should force a realloc
+	errors += fail_not_equal( state, 17, "bytes copied to trace (a) did not match expected size (b)" );
+
+	state = rmr_get_trace( mbuf, src_buf, 17 );
+	errors += fail_not_equal( state, 17, "bytes retrieved from trace (a) did not match expected size (b)" );
+	state = strcmp( src_buf, "foo bar was here" );
+	errors+= fail_not_equal( state, 0, "compare of pulled trace info did not match" );
+
+	i = rmr_get_trlen( mbuf );
 	
 
 	return errors > 0;			// overall exit code bad if errors
diff --git a/test/mbuf_api_test.c b/test/mbuf_api_test.c
index 858efdc..30427b1 100644
--- a/test/mbuf_api_test.c
+++ b/test/mbuf_api_test.c
@@ -22,6 +22,10 @@
 /*
 	Mnemonic:	mbuf_api_test.c
 	Abstract:	Unit tests for the mbuf common API functions.
+				To allow the mbuf functions to be tested without the bulk of the
+				RMr mechanics, we dummy up a couple of functions that are in 
+				rmr[_nng].c. 
+
 	Author:		E. Scott Daniels
 	Date:		2 April 2019
 */
@@ -45,6 +49,47 @@
 #include "test_support.c"						// our private library of test tools
 #include "mbuf_api_static_test.c"				// test functions
 
+// --- dummies -------------------------------------------------------------------
+
+/*
+	This will leak, but we're not here to test free.
+*/
+extern void rmr_free_msg( rmr_mbuf_t* mbuf ) {
+	return;
+}
+
+/*
+	Minimal buffer realloc to allow api to be tested without coverage hit if
+	we actually pulled in the sr static set.
+
+	WARNING:  this is NOT a complete realloc.  We assume that we are testing
+			just the trace length adjustment portion of the set_trace() 
+			API and are not striving to test the real realloc function. That
+			will be tested when the mbuf_api_static_test code is used by the
+			more generic RMr test.  So, not all fields in the realloc'd buffer
+			can be used.
+*/
+extern rmr_mbuf_t* rmr_realloc_msg( rmr_mbuf_t* msg, int new_tr_size ) {
+	rmr_mbuf_t*	new_msg;
+	uta_mhdr_t* hdr;
+
+	new_msg = (rmr_mbuf_t *) malloc( sizeof *new_msg );
+	new_msg->tp_buf = (void *) malloc( 2048 );
+	memset( new_msg->tp_buf, 0, 2048 );
+	hdr = (uta_mhdr_t*) new_msg->tp_buf;
+	SET_HDR_LEN( hdr );
+	SET_HDR_TR_LEN( hdr, new_tr_size );
+
+	new_msg->payload = new_msg->tp_buf + new_tr_size;
+	new_msg->header = new_msg->tp_buf;
+	new_msg->alloc_len = 2048;
+	new_msg->len = msg->len;
+	
+	return new_msg;
+}
+
+// --------------------------------------------------------------------------------
+
 int main( ) {
 	int errors = 0;
 
diff --git a/test/rmr_nng_api_static_test.c b/test/rmr_nng_api_static_test.c
index e9ecb72..3d09f28 100644
--- a/test/rmr_nng_api_static_test.c
+++ b/test/rmr_nng_api_static_test.c
@@ -73,7 +73,7 @@
 	}
 
 	for( i = 0; i < n; i++ ) {
-fprintf( stderr, "mass send\n" );
+		//fprintf( stderr, "mass send\n" );
 		msg->len = 100;
 		msg->mtype = 1;
 		msg->state = 999;
@@ -91,6 +91,7 @@
 	int		v = 0;					// some value
 	char	wbuf[128];
 	int		i;
+	int		state;
 
 	v = rmr_ready( NULL );
 	errors += fail_if( v != 0, "rmr_ready returned true before initialisation" );
@@ -253,6 +254,22 @@
 	}
 	errors += fail_if( i >= 40, "torcv_msg never returned a timeout" );
 
+
+	// ---- trace things that are not a part of the mbuf_api functions and thus must be tested here
+	state = rmr_init_trace( NULL, 37 );						// coverage test nil context
+	errors += fail_not_equal( state, 0, "attempt to initialise trace with nil context returned non-zero state (a)" );
+	errors += fail_if_equal( errno, 0, "attempt to initialise trace with nil context did not set errno as expected" );
+
+	state = rmr_init_trace( rmc, 37 );
+	errors += fail_if_equal( state, 0, "attempt to set trace len in context was not successful" );
+	errors += fail_not_equal( errno, 0, "attempt to set trace len in context did not clear errno" );
+
+	msg = rmr_tralloc_msg( rmc, 1024, 17, "1904308620110417" );
+	errors += fail_if_nil( msg, "attempt to allocate message with trace data returned nil message" );
+	state = rmr_get_trace( msg, wbuf, 17 );
+	errors += fail_not_equal( state, 17, "len of trace data (a) returned after msg allocation was not expected size (b)" );
+	state = strcmp( wbuf, "1904308620110417" );
+	errors += fail_not_equal( state, 0, "trace data returned after tralloc was not correct" );
 	
 	em_send_failures = 1;
 	send_n_msgs( rmc, 30 );			// send 30 messages with emulation failures
@@ -262,10 +279,6 @@
 	rmr_close( NULL );			// drive for coverage
 	rmr_close( rmc );			// no return to check; drive for coverage
 
-//extern rmr_mbuf_t* rmr_mtosend_msg( void* vctx, rmr_mbuf_t* msg, int max_to ) {
-//extern rmr_mbuf_t* rmr_torcv_msg( void* vctx, rmr_mbuf_t* old_msg, int ms_to ) {
-
-
 
 	if( ! errors ) {
 		fprintf( stderr, "<INFO> all RMr API tests pass\n" );
diff --git a/test/rmr_nng_test.c b/test/rmr_nng_test.c
index 1ebdb94..0b3068e 100644
--- a/test/rmr_nng_test.c
+++ b/test/rmr_nng_test.c
@@ -71,6 +71,7 @@
 
 #include "../src/common/src/symtab.c"
 #include "../src/nng/src/rmr_nng.c"
+#include "../src/common/src/mbuf_api.c"
 
 static void gen_rt( uta_ctx_t* ctx );		// defined in sr_nng_static_test, but used by a few others (eliminate order requirement below)
 
@@ -84,6 +85,7 @@
 #include "sr_nng_static_test.c"
 #include "wormhole_static_test.c"
 #include "rmr_nng_api_static_test.c"
+#include "mbuf_api_static_test.c"
 
 
 /*
@@ -120,6 +122,10 @@
 	errors += sr_nng_test();				// test the send/receive static functions
 	fprintf( stderr, "<INFO> error count: %d\n", errors );
 
+	fprintf( stderr, "<INFO> starting mbuf api tests\n" );
+	errors +=  mbuf_api_test( );
+	fprintf( stderr, "<INFO> error count: %d\n", errors );
+
 	if( errors == 0 ) {
 		fprintf( stderr, "<PASS> all tests were OK\n" );
 	} else {
diff --git a/test/rt_static_test.c b/test/rt_static_test.c
index f1e6981..26f81b7 100644
--- a/test/rt_static_test.c
+++ b/test/rt_static_test.c
@@ -75,8 +75,9 @@
 	nng_socket nn_sock;		// this is a struct in nng, so difficult to validate
 
 	setenv( "ENV_VERBOSE_FILE", ".ut_rmr_verbose", 1 );			// allow for verbose code in rtc to be driven
-	i = open( ".rmr_verbose", O_CREAT, 0664 );
+	i = open( ".ut_rmr_verbose", O_RDWR | O_CREAT, 0644 );
 	if( i >= 0 ) {
+		write( 1, "2\n", 2 );
 		close( i );
 	}
 
diff --git a/test/sr_nng_static_test.c b/test/sr_nng_static_test.c
index 69090a1..9b936cc 100644
--- a/test/sr_nng_static_test.c
+++ b/test/sr_nng_static_test.c
@@ -173,14 +173,16 @@
 	errors += fail_if( state != 99, "xlate_nng_state did not return  default for unknown error" );
 	errors += fail_if( errno == 0, "xlate_nng_state did not set errno (6)" );
 
-	// ---- drive rtc in a 'static' (not pthreaded) mode -----
-	setenv( "ENV_VERBOSE_FILE", ".ut_rmr_verbose", 1 );			// allow for verbose code in rtc to be driven
-	i = open( ".rmr_verbose", O_CREAT, 0664 );
+	// ---- drive rtc in a 'static' (not pthreaded) mode to get some coverage; no 'results' to be verified -----
+	setenv( ENV_RTG_RAW, "1", 1 );								// rtc should expect raw messages (mostly coverage here)
+	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 );
 	if( i >= 0 ) {
-		write( i, "0\n", 2 );
+		write( i, "2\n", 2 );
 		close( i );
 	}
 	ctx->shutdown = 1;			// should force rtc to quit on first pass
+	rtc( NULL );				// coverage test with nil pointer
 	rtc( ctx );
 	
 
diff --git a/test/symtab_test.c b/test/symtab_test.c
index 76b2765..e2efa2b 100644
--- a/test/symtab_test.c
+++ b/test/symtab_test.c
@@ -27,6 +27,8 @@
 	Author: 	E. Scott Daniels
 */
 
+#define NO_DUMMY_RMR 1			// no dummy rmr functions; we don't pull in rmr.h or agnostic.h
+
 #include "../src/common/include/rmr_symtab.h"
 #include "../src/common/src/symtab.c"
 
diff --git a/test/test_support.c b/test/test_support.c
index 4ed976c..49012c4 100644
--- a/test/test_support.c
+++ b/test/test_support.c
@@ -138,4 +138,33 @@
 	return a != b ? GOOD : BAD;			// user may override good/bad so do NOT return a==b directly!
 }
 
+
+#ifndef NO_DUMMY_RMR
+/*
+	Dummy message allocator for testing without sr_static functions
+*/
+static rmr_mbuf_t* test_mk_msg( int len, int tr_len ) {
+	rmr_mbuf_t*	new_msg;
+	uta_mhdr_t* hdr;
+	size_t	alen;
+
+	alen = sizeof( *hdr ) + tr_len + len;
+
+	new_msg = (rmr_mbuf_t *) malloc( sizeof *new_msg );
+	new_msg->tp_buf = (void *) malloc( alen );
+	memset( new_msg->tp_buf, 0, alen );
+
+	hdr = (uta_mhdr_t*) new_msg->tp_buf;
+	SET_HDR_LEN( hdr );
+	SET_HDR_TR_LEN( hdr, tr_len );
+
+	new_msg->header = new_msg->tp_buf;
+	new_msg->payload =  new_msg->header + PAYLOAD_OFFSET( hdr );
+	new_msg->alloc_len = alen;
+	new_msg->len = 0;
+	
+	return new_msg;
+}
+#endif
+
 #endif
diff --git a/test/unit_test.ksh b/test/unit_test.ksh
index d876c0e..21848af 100755
--- a/test/unit_test.ksh
+++ b/test/unit_test.ksh
@@ -266,6 +266,7 @@
 verbose=0
 show_all=1					# show all things -F sets to show failures only
 strict=0					# -s (strict) will set; when off, coverage state ignored in final pass/fail
+show_output=0				# show output from each test execution (-S)
 
 while [[ $1 == "-"* ]]
 do
@@ -282,6 +283,7 @@
 		-F)	show_all=0;;
 
 		-s)	strict=1;;					# coverage counts toward pass/fail state
+		-S)	show_output=1;;				# test output shown even on success
 		-v)	(( verbose++ ));;
 
 		-h) 	usage; exit 0;;
@@ -354,6 +356,13 @@
 		cat /tmp/PID$$.log
 		(( ut_errors++ ))				# cause failure even if not in strict mode
 		continue						# skip coverage tests for this
+	else
+		if (( show_output ))
+		then
+			printf "\n============= test programme output =======================\n"
+			cat /tmp/PID$$.log
+			printf "===========================================================\n"
+		fi
 	fi
 
 	(