blob: 8d83c381bef22476f6e41abcadd13f1bfc5c023a [file] [log] [blame]
Ron Shachame7dfeb82020-04-24 14:46:48 -04001#!/usr/bin/env bash
2# vim: ts=4 sw=4 noet :
3
4#==================================================================================
5# Copyright (c) 2020 Nokia
6# Copyright (c) 2020 AT&T Intellectual Property.
7#
8# Licensed under the Apache License, Version 2.0 (the "License");
9# you may not use this file except in compliance with the License.
10# You may obtain a copy of the License at
11#
12# http://www.apache.org/licenses/LICENSE-2.0
13#
14# Unless required by applicable law or agreed to in writing, software
15# distributed under the License is distributed on an "AS IS" BASIS,
16# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17# See the License for the specific language governing permissions and
18# limitations under the License.
19#==================================================================================
20
E. Scott Danielsd8461662021-01-22 08:16:05 -050021# LICENSE NOTE:
22# this code is based on the unit test code in the o-ran-sc RMR repositiory which
23# is covered by the original license above, and thus that license governs this
24# extension as well.
25# ---------------------------------------------------------------------------------
26
Ron Shachame7dfeb82020-04-24 14:46:48 -040027#
28# Parse the .gcov file and discount any unexecuted lines which are in if()
29# blocks which are testing the result of alloc/malloc calls, or testing for
30# nil pointers. The feeling is that these might not be possible to drive
31# and shoudn't contribute to coverage deficiencies.
32#
33# In verbose mode, the .gcov file is written to stdout and any unexecuted
34# line which is discounted is marked with ===== replacing the ##### marking
35# that gcov wrote.
36#
37# The return value is 0 for pass; non-zero for fail.
38#
39function discount_ck {
40 typeset f="$1"
41
42 mct=80 # force minimum coverage threshold for passing
43
44 if [[ ! -f $f ]]
45 then
46 if [[ -f ${f##*/} ]]
47 then
48 f=${f##*/}
49 else
50 echo "cant find: $f"
51 return
52 fi
53 fi
54
55 awk -v module_cov_target=$mct \
56 -v cfail=${cfail:-WARN} \
57 -v show_all=$show_all \
58 -v full_name="${1}" \
59 -v module="${f%.*}" \
60 -v chatty=$chatty \
61 -v replace_flags=$replace_flags \
62 '
63 function spit_line( ) {
64 if( chatty ) {
65 printf( "%s\n", $0 )
66 }
67 }
68
69 /-:/ { # skip unexecutable lines
70 spit_line()
71 seq++ # allow blank lines in a sequence group
72 next
73 }
74
75 {
76 nexec++ # number of executable lines
77 }
78
79 /#####:/ {
80 unexec++;
81 if( $2+0 != seq+1 ) {
82 prev_malloc = 0
83 prev_if = 0
84 seq = 0
85 spit_line()
86 next
87 }
88
89 if( prev_if && prev_malloc ) {
90 if( prev_malloc ) {
91 #printf( "allow discount: %s\n", $0 )
92 if( replace_flags ) {
93 gsub( "#####", " 1", $0 )
94 //gsub( "#####", "=====", $0 )
95 }
96 discount++;
97 }
98 }
99
100 seq++;;
101 spit_line()
102 next;
103 }
104
105 /if[(].*alloc.*{/ { # if( (x = malloc( ... )) != NULL ) or if( (p = sym_alloc(...)) != NULL )
106 seq = $2+0
107 prev_malloc = 1
108 prev_if = 1
109 spit_line()
110 next
111 }
112
113 /if[(].* == NULL/ { # a nil check likely not easily forced if it wasnt driven
114 prev_malloc = 1
115 prev_if = 1
116 spit_line()
117 seq = $2+0
118 next
119 }
120
121 /if[(]/ {
122 if( seq+1 == $2+0 && prev_malloc ) { // malloc on previous line
123 prev_if = 1
124 } else {
125 prev_malloc = 0
126 prev_if = 0
127 }
128 spit_line()
129 next
130 }
131
132 /alloc[(]/ {
133 seq = $2+0
134 prev_malloc = 1
135 spit_line()
136 next
137 }
138
139 {
140 spit_line()
141 }
142
143 END {
144 net = unexec - discount
145 orig_cov = ((nexec-unexec)/nexec)*100 # original coverage
146 adj_cov = ((nexec-net)/nexec)*100 # coverage after discount
147 pass_fail = adj_cov < module_cov_target ? cfail : "PASS"
148 rc = adj_cov < module_cov_target ? 1 : 0
149 if( pass_fail == cfail || show_all ) {
150 if( chatty ) {
151 printf( "[%s] %s executable=%d unexecuted=%d discounted=%d net_unex=%d cov=%d%% ==> %d%% target=%d%%\n",
152 pass_fail, full_name ? full_name : module, nexec, unexec, discount, net, orig_cov, adj_cov, module_cov_target )
153 } else {
154 printf( "[%s] %d%% (%d%%) %s\n", pass_fail, adj_cov, orig_cov, full_name ? full_name : module )
155 }
156 }
157
158 exit( rc )
159 }
160 ' $f
161}
162
163# ----------------------------------------------------------------------
164show_all=1 # turn off to hide passing modules (-q)
165chatty=0 # -v turns on to provide more info when we do speak
166
167while [[ $1 == "-"* ]]
168do
169 case $1 in
170 -q) show_all=0;;
171 -v) chatty=1;;
172
173 *) echo "unrecognised option: $1"
174 echo "usage: $0 [-q] gcov-file-list"
175 exit 1
176 ;;
177 esac
178 shift
179done
180
181
182while [[ -n $1 ]]
183do
184 discount_ck $1
185 shift
186done