Add full unit tests for listener
[ric-app/mc.git] / sidecars / listener / discount_chk.ksh
1 #!/usr/bin/env bash
2
3 #==================================================================================
4 #        Copyright (c) 2018-2019 AT&T Intellectual Property.
5 #
6 #   Licensed under the Apache License, Version 2.0 (the "License");
7 #   you may not use this file except in compliance with the License.
8 #   You may obtain a copy of the License at
9 #
10 #       http://www.apache.org/licenses/LICENSE-2.0
11 #
12 #   Unless required by applicable law or agreed to in writing, software
13 #   distributed under the License is distributed on an "AS IS" BASIS,
14 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 #   See the License for the specific language governing permissions and
16 #   limitations under the License.
17 #==================================================================================
18
19
20 #
21 #       Mnemonic:       discount_chk.ksh
22 #       Abstract:       This checks the gcov output from unit tests to determine
23 #                               what number of lines of code are highly untestable. Primararily
24 #                               these are lines in blocks which are executed when systems
25 #                               calles (e.g. malloc) fail.
26 #
27 #       Date:           10 December 2019
28 #       Author:         E. Scott Daniels
29 # -------------------------------------------------------------------------
30
31
32 #
33 #       Parse the .gcov file and discount any unexecuted lines which are in if()
34 #       blocks that are testing the result of alloc/malloc calls, or testing for
35 #       nil pointers.  The feeling is that these might not be possible to drive
36 #       and shoudn't contribute to coverage deficiencies.
37 #
38 #       In verbose mode, the .gcov file is written to stdout and any unexecuted
39 #       line which is discounted is marked with ===== replacing the ##### marking
40 #       that gcov wrote.
41 #
42 #       The return value is 0 for pass; non-zero for fail.
43 function discount_gcov {
44         typeset f="$1"
45
46         #mct=$( get_mct ${1%.gcov} )                    # see if a special coverage target is defined for this
47         mct=80
48
49         if [[ ! -f $1 ]]
50         then
51                 if [[ -f ${1##*/} ]]
52                 then
53                         f=${1##*/}
54                 else
55                         echo "cant find: $f"
56                         return
57                 fi
58         fi
59
60         awk -v module_cov_target=$mct \
61                 -v cfail=${cfail:-WARN} \
62                 -v show_all=$show_all \
63                 -v full_name="${1}"  \
64                 -v module="${f%.*}"  \
65                 -v chatty=$chatty \
66                 -v replace_flags=$replace_flags \
67         '
68         function spit_line( ) {
69                 if( chatty ) {
70                         printf( "%s\n", $0 )
71                 }
72         }
73
74         /-:/ {                          # skip unexecutable lines
75                 spit_line()
76                 seq++                                   # allow blank lines in a sequence group
77                 next
78         }
79
80         {
81                 nexec++                 # number of executable lines
82         }
83
84         /#####:/ {
85                 unexec++;
86                 if( $2+0 != seq+1 ) {
87                         prev_malloc = 0
88                         prev_if = 0
89                         seq = 0
90                         spit_line()
91                         next
92                 }
93
94                 if( prev_if && prev_malloc ) {
95                         if( prev_malloc ) {
96                                 #printf( "allow discount: %s\n", $0 )
97                                 if( replace_flags ) {
98                                         if( replace_flags == 1 ) {
99                                                 gsub( "#####", "    1", $0 )
100                                         } else {
101                                                 gsub( "#####", "=====", $0 )
102                                         }
103                                 }
104                                 discount++;
105                         }
106                 }
107
108                 seq++;;
109                 spit_line()
110                 next;
111         }
112
113         /if[(].*errno ==.*{/ ||                 # if( errno == ... ) assume error check
114
115         /if[(].*alloc.*{/ {                     # if( (x = malloc( ... )) != NULL ) or if( (p = sym_alloc(...)) != NULL )
116                 prev_malloc = 1
117                 prev_if = 1
118                 spit_line()
119                 seq = $2+0
120                 next
121         }
122
123         /if[(].* == NULL/ {                             # a nil check likely not easily forced if it wasnt driven
124                 prev_malloc = 1
125                 prev_if = 1
126                 spit_line()
127                 seq = $2+0
128                 next
129         }
130
131         /if[(]/ {
132                 if( seq+1 == $2+0 && prev_malloc ) {            # malloc on previous line
133                         prev_if = 1
134                 } else {
135                         prev_malloc = 0
136                         prev_if = 0
137                 }
138                 spit_line()
139                 next
140         }
141
142         /alloc[(]/ {
143                 seq = $2+0
144                 prev_malloc = 1
145                 spit_line()
146                 next
147         }
148
149         {
150                 spit_line()
151         }
152
153         END {
154                 net = unexec - discount
155                 orig_cov = ((nexec-unexec)/nexec)*100           # original coverage
156                 adj_cov = ((nexec-net)/nexec)*100                       # coverage after discount
157                 pass_fail = adj_cov < module_cov_target ? cfail : "PASS"
158                 rc = adj_cov < module_cov_target ? 1 : 0
159                 if( pass_fail == cfail || show_all ) {
160                         if( chatty ) {
161                                 printf( "[%s] %s executable=%d unexecuted=%d discounted=%d net_unex=%d  cov=%d%% ==> %d%%  target=%d%%\n",
162                                         pass_fail, full_name ? full_name : module, nexec, unexec, discount, net, orig_cov, adj_cov, module_cov_target )
163                         } else {
164                                 printf( "[%s] %d%% (%d%%) %s\n", pass_fail, adj_cov, orig_cov, full_name ? full_name : module )
165                         }
166                 }
167
168                 exit( rc )
169         }
170         ' $f
171 }
172
173 # ----------------------------------------------------------------
174
175 ignore_list="main"
176 module_cov_target=80
177 chatty=0
178 show_all=1
179 replace_flags=1
180 cfail="FAIL"
181
182 while [[ $1 == -* ]]
183 do
184         case $1 in 
185                 -a)     show_all-1;;                                    # only show things not passing
186                 -c) module_cov_target=$2;;                      # coverage target for module
187                 -r)     replace_flag=$2; shift;;                # replace with ==== if 2; no repalce if 0
188                 -V)     chatty=1;;                                              # show "dcov" output
189         esac
190
191         shift
192 done
193
194 for ckf in "$@"
195 do
196         discount_gcov ${ckf%.gcov}.gcov
197 done