Initial commit of TS xapp

Signed-off-by: Ron Shacham <rshacham@research.att.com>
Change-Id: I1e08ef0cbee769d365f7b4f27a4548161ae4703c
diff --git a/test/parse_gcov.sh b/test/parse_gcov.sh
new file mode 100755
index 0000000..d69a88b
--- /dev/null
+++ b/test/parse_gcov.sh
@@ -0,0 +1,180 @@
+#!/usr/bin/env bash
+# vim: ts=4 sw=4 noet :
+
+#==================================================================================
+#       Copyright (c) 2020 Nokia
+#       Copyright (c) 2020 AT&T Intellectual Property.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#==================================================================================
+
+#
+#	Parse the .gcov file and discount any unexecuted lines which are in if()
+#	blocks which are testing the result of alloc/malloc calls, or testing for
+#	nil pointers.  The feeling is that these might not be possible to drive
+#	and shoudn't contribute to coverage deficiencies.
+#
+#	In verbose mode, the .gcov file is written to stdout and any unexecuted
+#	line which is discounted is marked with ===== replacing the ##### marking
+#	that gcov wrote.
+#
+#	The return value is 0 for pass; non-zero for fail.
+#
+function discount_ck {
+	typeset f="$1"
+
+	mct=80							# force minimum coverage threshold for passing
+
+	if [[ ! -f $f ]]
+	then
+		if [[ -f ${f##*/} ]]
+		then
+			f=${f##*/}
+		else
+			echo "cant find: $f"
+			return
+		fi
+	fi
+
+	awk -v module_cov_target=$mct \
+		-v cfail=${cfail:-WARN} \
+		-v show_all=$show_all \
+		-v full_name="${1}"  \
+		-v module="${f%.*}"  \
+		-v chatty=$chatty \
+		-v replace_flags=$replace_flags \
+	'
+	function spit_line( ) {
+		if( chatty ) {
+			printf( "%s\n", $0 )
+		}
+	}
+
+	/-:/ { 						# skip unexecutable lines
+		spit_line()
+		seq++					# allow blank lines in a sequence group
+		next
+	}
+
+	{
+		nexec++					# number of executable lines
+	}
+
+	/#####:/ {
+		unexec++;
+		if( $2+0 != seq+1 ) {
+			prev_malloc = 0
+			prev_if = 0
+			seq = 0
+			spit_line()
+			next
+		}
+
+		if( prev_if && prev_malloc ) {
+			if( prev_malloc ) {
+				#printf( "allow discount: %s\n", $0 )
+				if( replace_flags ) {
+					gsub( "#####", "    1", $0 )
+					//gsub( "#####", "=====", $0 )
+				}
+				discount++;
+			}
+		}
+
+		seq++;;
+		spit_line()
+		next;
+	}
+
+	/if[(].*alloc.*{/ {			# if( (x = malloc( ... )) != NULL ) or if( (p = sym_alloc(...)) != NULL )
+		seq = $2+0
+		prev_malloc = 1
+		prev_if = 1
+		spit_line()
+		next
+	}
+
+	/if[(].* == NULL/ {				# a nil check likely not easily forced if it wasnt driven
+		prev_malloc = 1
+		prev_if = 1
+		spit_line()
+		seq = $2+0
+		next
+	}
+
+	/if[(]/ {
+		if( seq+1 == $2+0 && prev_malloc ) {		// malloc on previous line
+			prev_if = 1
+		} else {
+			prev_malloc = 0
+			prev_if = 0
+		}
+		spit_line()
+		next
+	}
+
+	/alloc[(]/ {
+		seq = $2+0
+		prev_malloc = 1
+		spit_line()
+		next
+	}
+
+	{
+		spit_line()
+	}
+
+	END {
+		net = unexec - discount
+		orig_cov = ((nexec-unexec)/nexec)*100		# original coverage
+		adj_cov = ((nexec-net)/nexec)*100			# coverage after discount
+		pass_fail = adj_cov < module_cov_target ? cfail : "PASS"
+		rc = adj_cov < module_cov_target ? 1 : 0
+		if( pass_fail == cfail || show_all ) {
+			if( chatty ) {
+				printf( "[%s] %s executable=%d unexecuted=%d discounted=%d net_unex=%d  cov=%d%% ==> %d%%  target=%d%%\n",
+					pass_fail, full_name ? full_name : module, nexec, unexec, discount, net, orig_cov, adj_cov, module_cov_target )
+			} else {
+				printf( "[%s] %d%% (%d%%) %s\n", pass_fail, adj_cov, orig_cov, full_name ? full_name : module )
+			}
+		}
+
+		exit( rc )
+	}
+	' $f
+}
+
+# ----------------------------------------------------------------------
+show_all=1			# turn off to hide passing modules (-q)
+chatty=0			# -v turns on to provide more info when we do speak
+
+while [[ $1 == "-"* ]]
+do
+	case $1 in 
+		-q)	show_all=0;;
+		-v)	chatty=1;;
+
+		*)	echo "unrecognised option: $1"
+			echo "usage: $0 [-q] gcov-file-list"
+			exit 1
+			;;
+	esac
+	shift
+done
+
+
+while [[ -n $1 ]]
+do
+	discount_ck $1
+	shift
+done