1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371
|
#!/bin/bash
# Run this script in cpptests/ to get a report on the tests.
# shellcheck disable=SC2086
set -e
#set -x
spatch=../spatch.opt
declare -A FAILED_RUN
declare -A FAILED_PP
declare -A FAILED_CP
declare -A TEST_CASE_BROKEN
declare -A TEST_CASE_FAILS
declare -A REFTAGS
declare -A REFTOTEST
cat_tags_file() {
cat << EOF
access_specifiers_0.cocci v20240610:language/access
access_specifiers_1.cocci v20240610:language/access
access_specifiers_1_class.cocci v20240610:language/access v20240610:language/class
access_specifiers_2.cocci v20240610:language/access
access_specifiers_3.cocci v20240610:language/access
access_specifiers_4.cocci v20240610:language/access
addremvec.cocci v20240610:language/template_parameters#Template_arguments
aggregate_initialization.cocci v20240610:language/aggregate_initialization#Syntax
attributeu.cocci v20240610:language/attributes
auto.cocci v20240610:language/auto
autoloop.cocci v20240610:language/range-for
bool1.cocci v20240610:language/function
bracket.cocci v20240610:language/aggregate_initialization#Syntax
bracketed_expression_assignment.cocci v20240610:language/aggregate_initialization#Syntax
braced_init_list.cocci v20240610:language/explicit_cast#Explanation
braced_init_list_return.cocci v20240610:language/return
braced_init_list_assign.cocci v20240610:language/initialization#Initializer
braced_init_list_arg.cocci v20240610:language/initialization#Initializer v20240610:language/function
cdstr.cocci v20240610:language/constructor
snip_field_bad.cocci v20240610:language/class
snip_field_and_keep_access_specifier.cocci v20240610:language/class v20240610:language/access
classfinal.cocci v20240610:language/final
complexcpp.cocci v20240610:numeric/complex v20240610:header/complex
cuda1.cocci v20240610:language/operator_other#Built-in_function_call_operator
cuda.cocci v20240610:language/function#Function_definition
cuda_noattr.cocci v20240610:language/operator_other#Built-in_function_call_operator
decl_andand_ref.cocci v20240610:language/reference#Rvalue_references
decl_and_ref.cocci v20240610:language/reference#Rvalue_references
decl_ptr_ref.cocci v20240610:language/pointer#Pointers
decltype.cocci v20240610:language/decltype
decltype_matches_type.cocci v20240610:language/decltype
delete_array.cocci v20240610:language/delete#Syntax
delete.cocci v20240610:language/delete#Syntax
destructor_constructor_parse v20240610:language/access v20240610:language/class v20240610:language/destructor
destructor_constructor_parse_smpl v20240610:language/access v20240610:language/class v20240610:language/destructor
emptytmp.cocci v20240610:language/template_parameters#Template_arguments
endcolon.cocci v20240610:language/qualified_lookup
endline.cocci v20240610:language/template_parameters#Template_arguments v20240610:language/qualified_lookup
enumcpp.cocci v20240610:language/enum
fieldtmp.cocci v20240610:language/operator_member_access
finalclass.cocci v20240610:language/final#Syntax
forc.cocci v20240610:language/template_parameters#Template_arguments
forrange2.cocci v20240610:language/range-for
forrange.cocci v20240610:language/range-for
inh1.cocci v20240610:language/derived_class
init3tst.cocci v20240610:language/aggregate_initialization#Syntax
instfour.cocci v20240610:language/template_parameters#Template_arguments
instruct.cocci v20240610:language/using_declaration v20240610:preprocessor/impl
list_and_aggregate_initialization_isomorphism_off.cocci v20240610:language/aggregate_initialization#Syntax
list_and_aggregate_initialization_isomorphism_on.cocci v20240610:language/aggregate_initialization#Syntax
list_initialization.cocci v20240610:language/aggregate_initialization#Syntax
local_macro_fn_def_and_call.cocci v20240610:preprocessor
macro_stmt_when_fn_type.cocci v20240610:preprocessor
match_bracket_expressions_assignment_broken.cocci v20240610:language/aggregate_initialization#Syntax
miniclass.cocci v20240610:language/class
namespace_alias_definition.cocci v20240610:language/namespace_alias
namespace_nested1.cocci v20240610:language/namespace
namespace_nested2.cocci v20240610:language/namespace
namespace_nested3.cocci v20240610:language/namespace
namespace_nested4.cocci v20240610:language/namespace
new2.cocci v20240610:language/new#Syntax
new3.cocci v20240610:language/new#Syntax
new.cocci v20240610:language/new#Syntax
newsimple.cocci v20240610:language/new#Syntax
noexcept.cocci v20240610:language/noexcept_spec
notpp.cocci v20240610:keyword/not
opeq.cocci v20240610:language/operators
protocpp.cocci v20240610:language/reference#Rvalue_references
qualclass.cocci v20240610:language/derived_class v20240610:language/qualified_lookup
qual.cocci v20240610:language/qualified_lookup
sizet.cocci v20240610:cpp/types/size_t
snip_field.cocci v20240610:language/class
tempinstfour.cocci v20240610:language/template_parameters#Template_arguments
templates1.cocci v20240610:language/template_parameters#Template_arguments
template_test.cocci v20240610:language/template_parameters#Template_arguments
templates_partial_specialization v20240610:language/template_parameters#Template_arguments v20240610:language/partial_specialization
tmpinit.cocci v20240610:language/template_parameters#Template_arguments
tmpinst2.cocci v20240610:language/template_parameters#Template_arguments
tmpinst4.cocci v20240610:language/template_parameters#Template_arguments
tmpinst5.cocci v20240610:language/template_parameters#Template_arguments
try_catch1.cocci v20240610:language/try v20240610:language/catch
try_catch2.cocci v20240610:language/try v20240610:language/catch
try_catch.cocci v20240610:language/try v20240610:language/catch
using1.cocci v20240610:language/using_declaration
using2.cocci v20240610:language/using_declaration
using3.cocci v20240610:language/using_declaration
using4.cocci v20240610:language/using_declaration
usingtest.cocci v20240610:language/using_declaration
usingtype.cocci v20240610:language/using_declaration
vconstr.cocci v20240610:language/virtual v20240610:language/destructor
virtual_constructor.cocci v20240610:language/virtual v20240610:language/destructor
while_init_condition.cocci v20240610:language/while
while_init_condition_smpl.cocci v20240610:language/while
EOF
}
read_tags_file() {
while read cf tags;
do
if test $cf = '#'; then continue; fi
tn=${cf/.cocci/};
REFTAGS[$tn]=$tags
#echo ${REFTAGS[$cf]}
done < <( cat_tags_file )
}
populate_ref_to_test_array() {
for tn in ${!REFTAGS[*]}; do
for tag in ${REFTAGS[$tn]}; do
if [[ $tag =~ v20240610: ]] ; then
url='https://en.cppreference.com/w/cpp/'${tag/v20240610:/};
REFTOTEST[$url]+=" $tn"
fi
done
done
}
check_tags_sanity() {
local rc=0;
local UNTAGGED_TEST_FILES=''
for cf in *.cocci; do
tn=${cf/.cocci/};
if test -z "${REFTAGS[$tn]}"; then UNTAGGED_TEST_FILES+=" $cf"; fi
done
local ORPHANED_TEST_LINES=''
for tn in ${!REFTAGS[*]}; do
if ! test -f $tn.cocci ; then ORPHANED_TEST_LINES+=" $tn"; fi
done
if test -n "${UNTAGGED_TEST_FILES}"; then echo "ERROR: Untagged test files: ${UNTAGGED_TEST_FILES}"; rc=1; fi
if test -n "${ORPHANED_TEST_LINES}"; then echo "ERROR: Orphaned test lines: ${ORPHANED_TEST_LINES}"; rc=1; fi
if test "${rc}" != 0; then exit $rc; fi
}
read_tags_file
populate_ref_to_test_array
check_tags_sanity
for cf in *.cocci; do
tn=${cf/.cocci/};
if ! ( head -n1 $cf | grep -q -- --c++ ) ; then echo "you forgot --c++ flag in $cf file"; false; fi # --c++ is required
set +e
$spatch --test $tn
FAILED_RUN[$tn]=$?
set -e
set +e
$spatch --parse-cocci $tn.cocci
FAILED_PP[$tn]=$?
set -e
set +e
( $spatch --c++ --parse-c $tn.cpp && $spatch --c++ --parse-c $tn.cpp | grep -q '100.*good.or.passed' );
FAILED_CP[$tn]=$?;
set -e
if test ${FAILED_RUN[$tn]} = 0; then
cmpfile=$tn.cmp
set +e
$spatch --sp-file $tn.cocci $tn.cpp -o $cmpfile
TEST_CASE_BROKEN[$tn]=$?
cmp $tn.res $cmpfile
TEST_CASE_FAILS[$tn]=$?
set -e
fi
rm -f $cmpfile
set -e
done
function maybe_html_arrow()
{
if test -n "$WANT_HTML"; then echo '→'; else echo '->'; fi
}
function file_title()
{
echo "<CODE CLASS=\"H4\">$1</CODE>"
}
function header() {
local PRE='' POST=''
if test -n "$WANT_HTML"; then
PRE+="<H2>";
POST+="</H2>";
if test "$1" = '-n'; then shift; else POST+="<BR>"; fi
else
if test "$1" = '-n'; then PRE+='-n'; fi
fi
echo "$PRE" "$@" "$POST"
}
function to_href() {
if test $# = 0 ; then cat ; else echo "${1}"; fi | \
sed 's/^\(.\+\)$/\<A HREF="\1"\>\1\<\/A\>/g'
}
function to_href2() {
echo -n '<A HREF="'$1'">'$2'</A>'
}
function maybe_to_href() {
if test -n "$WANT_HTML"; then to_href $@; else echo $@; fi
}
function maybe_to_anchor_href() {
if test -n "$WANT_HTML"; then
while read -d ' ' td; do
#if test -z "$tn" ; then continue; fi
tn=${td//\*/}
#echo -n "bu:$tn"
to_href2 "#${tn}" "${td}"; echo -n ' '
done | sed 's/$/<BR>/g'
else
cat
fi
}
function cat_all_as_pre() {
for f in $1.cocci $1.cpp $1.res; do
#echo "<BR>"
file_title "$f"; echo -n ':'
#echo "<BR>"
! txt2html --prebegin 0 --bold_delimiter '' --italic_delimiter '' --underline_delimiter '' --extract "$f" # TODO: new2.res and a few others are missing
true # the above can fail
#echo "<BR>"
done
}
function test_reference() {
if test -n "$WANT_HTML"; then
tr -d ' ' | \
while read tn; do \
#echo "<BR>"
echo -n "<A ID=\"$tn\">"'</A>';
echo '<H3>Test: '
to_href2 "#$tn" "${tn}";
echo '</H3>'
#echo "<BR>"
cat_all_as_pre $tn
done
else
tr -d '\n' | cat
fi
}
print_results() {
if test -n "$WANT_HTML"; then
echo '<!DOCTYPE HTML><HTML><HEAD><TITLE>C++ Tests</TITLE>
<HEAD>
<STYLE>
BODY { COLOR: BLACK; BACKGROUND: WHITE; }
H1 { BACKGROUND: SILVER; COLOR: BLACK; }
H2 { BACKGROUND: SILVER; COLOR: BLACK; }
H3 { BACKGROUND: LIGHTGRAY; COLOR: BLACK; }
H4 { BACKGROUND: LIGHTGRAY; COLOR: BLACK; }
CODE.H4 { BACKGROUND: LIGHTGRAY; COLOR: BLACK; }
</STYLE>
</HEAD>
<BODY>
<H1> Coccinelle C++ Tests Results Summary</H1>
';
fi
echo
header -n 'CPPREFERENCE AND TESTS: '
for rn in ${!REFTOTEST[*]}; do
if test "${REFTOTEST[$rn]}" != ''; then
echo -n " `maybe_to_href $rn` `maybe_html_arrow` "
for tn in ${REFTOTEST[$rn]}; do
echo -n ${tn};
if test "${FAILED_PP[$tn]}" != 0 -o "${TEST_CASE_FAILS[$tn]}" != 0 -o "${FAILED_RUN[$tn]}" != 0; then echo -n '* '; else echo -n ' '; fi
done | maybe_to_anchor_href
echo
fi
done | sort
echo
header -n 'TEST CASE BROKEN (spatch ... exits non-zero): '
for tn in ${!TEST_CASE_BROKEN[*]}; do
if test ${TEST_CASE_BROKEN[$tn]} != 0; then
echo "$tn "
fi
done | sort | maybe_to_anchor_href
echo
header -n 'TEST FAILS (patches differ): '
for tn in ${!TEST_CASE_FAILS[*]}; do
if test ${TEST_CASE_FAILS[$tn]} != 0; then
echo "$tn "
fi
done | sort | maybe_to_anchor_href
echo
header -n 'PASSED SPATCH PARSE: '
for tn in ${!FAILED_PP[*]}; do
if test ${FAILED_PP[$tn]} = 0; then
echo "$tn "
fi
done | sort | maybe_to_anchor_href
echo
header -n 'FAILED SPATCH PARSE: '
for tn in ${!FAILED_PP[*]}; do
if test ${FAILED_PP[$tn]} != 0; then
echo "$tn "
fi
done | sort | maybe_to_anchor_href
echo
header -n 'PASSED SOURCE PARSE: '
for tn in ${!FAILED_CP[*]}; do
if test ${FAILED_CP[$tn]} = 0; then
echo "$tn "
fi
done | sort | maybe_to_anchor_href
echo
header -n 'FAILED SOURCE PARSE: '
for tn in ${!FAILED_CP[*]}; do
if test ${FAILED_CP[$tn]} != 0; then
echo "$tn "
fi
done | sort | maybe_to_anchor_href
echo
header -n 'PASSED TEST RUNS: '
for tn in ${!FAILED_RUN[*]}; do
if test ${FAILED_RUN[$tn]} = 0; then
echo "$tn "
fi
done | sort | maybe_to_anchor_href
echo
header -n 'FAILED TEST RUNS: '
for tn in ${!FAILED_RUN[*]}; do
if test ${FAILED_RUN[$tn]} != 0; then
echo "$tn "
fi
done | sort | maybe_to_anchor_href
echo
header -n 'SOURCES FOR ALL TESTS:'
for tn in ${!REFTAGS[*]}; do
echo "$tn "
done | sort | test_reference
echo
if test -n "$WANT_HTML"; then echo '<BODY><HTML>';fi
}
while getopts "o:" NAME; do
case $NAME in
o) WANT_HTML=$OPTARG;
which txt2html
;;
# TODO: add -h
*) false;;
esac
done
shift $((OPTIND-1))
if test -n "$WANT_HTML"; then
# TODO: Or MD?
print_results > "$WANT_HTML"
else
print_results
fi
|