blob: aaefd4ff6206f16e240595090db95e35989109be [file] [log] [blame]
#!/usr/bin/env bash
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.
FINDBUGS_HOME=${FINDBUGS_HOME:-}
FINDBUGS_WARNINGS_FAIL_PRECHECK=false
add_test_type findbugs
function findbugs_usage
{
yetus_add_option "--findbugs-home=<path>" "Findbugs home directory (default \${FINDBUGS_HOME})"
yetus_add_option "--findbugs-strict-precheck" "If there are Findbugs warnings during precheck, fail"
}
function findbugs_parse_args
{
local i
for i in "$@"; do
case ${i} in
--findbugs-home=*)
FINDBUGS_HOME=${i#*=}
;;
--findbugs-strict-precheck)
FINDBUGS_WARNINGS_FAIL_PRECHECK=true
;;
esac
done
}
## @description initialize the findbugs plug-in
## @audience private
## @stability evolving
## @replaceable no
function findbugs_initialize
{
if declare -f maven_add_install >/dev/null 2>&1; then
maven_add_install findbugs
fi
}
function findbugs_filefilter
{
local filename=$1
if [[ ${BUILDTOOL} == maven
|| ${BUILDTOOL} == ant ]]; then
if [[ ${filename} =~ \.java$
|| ${filename} =~ (^|/)findbugs-exclude.xml$ ]]; then
add_test findbugs
fi
fi
}
function findbugs_precheck
{
declare exec
declare status=0
if [[ -z ${FINDBUGS_HOME} ]]; then
yetus_error "FINDBUGS_HOME was not specified."
status=1
else
for exec in findbugs \
computeBugHistory \
convertXmlToText \
filterBugs \
setBugDatabaseInfo; do
if ! verify_command "${exec}" "${FINDBUGS_HOME}/bin/${exec}"; then
status=1
fi
done
fi
if [[ ${status} == 1 ]]; then
add_vote_table 0 findbugs "Findbugs executables are not available."
delete_test findbugs
fi
}
## @description Dequeue maven modules that lack java sources
## @audience private
## @stability evolving
## @replaceable no
function findbugs_maven_skipper
{
declare -i i=0
declare skiplist=()
declare modname
start_clock
#shellcheck disable=SC2153
until [[ ${i} -eq ${#MODULE[@]} ]]; do
# If there are no java source code in the module,
# skip parsing output xml file.
if [[ ! -d "${MODULE[${i}]}/src/main/java" ]]; then
skiplist=("${skiplist[@]}" "${MODULE[$i]}")
fi
((i=i+1))
done
i=0
for modname in "${skiplist[@]}"; do
dequeue_personality_module "${modname}"
done
if [[ -n "${modname}" ]]; then
if [[ "${BUILDMODE}" = patch ]]; then
add_vote_table 0 findbugs "Skipped patched modules with no Java source: ${skiplist[*]}"
else
add_vote_table 0 findbugs "Skipped ${#skiplist[@]} modules in the source tree with no Java source."
fi
fi
}
## @description Run the maven findbugs plugin and record found issues in a bug database
## @audience private
## @stability evolving
## @replaceable no
## @return 0 on success
## @return 1 on failure
## @param repostatus
function findbugs_runner
{
local name=$1
local module
local result=0
local fn
local warnings_file
local i=0
local savestop
personality_modules "${name}" findbugs
# strip out any modules that aren't actually java modules
# this can save a lot of time during testing
if [[ "${BUILDTOOL}" = maven ]]; then
findbugs_maven_skipper
fi
"${BUILDTOOL}_modules_worker" "${name}" findbugs
if [[ ${UNSUPPORTED_TEST} = true ]]; then
return 0
fi
#shellcheck disable=SC2153
until [[ ${i} -eq ${#MODULE[@]} ]]; do
if [[ ${MODULE_STATUS[${i}]} == -1 ]]; then
((result=result+1))
((i=i+1))
continue
fi
start_clock
offset_clock "${MODULE_STATUS_TIMER[${i}]}"
module="${MODULE[${i}]}"
fn=$(module_file_fragment "${module}")
case ${BUILDTOOL} in
maven)
file="${module}/target/findbugsXml.xml"
;;
ant)
file="${ANT_FINDBUGSXML}"
;;
esac
if [[ ! -f ${file} ]]; then
module_status ${i} -1 "" "${name}/${module} no findbugs output file (${file})"
((i=i+1))
continue
fi
warnings_file="${PATCH_DIR}/${name}-findbugs-${fn}-warnings"
cp -p "${file}" "${warnings_file}.xml"
if [[ ${name} == branch ]]; then
"${FINDBUGS_HOME}/bin/setBugDatabaseInfo" -name "${PATCH_BRANCH}" \
"${warnings_file}.xml" "${warnings_file}.xml"
else
"${FINDBUGS_HOME}/bin/setBugDatabaseInfo" -name patch \
"${warnings_file}.xml" "${warnings_file}.xml"
fi
if [[ $? != 0 ]]; then
savestop=$(stop_clock)
MODULE_STATUS_TIMER[${i}]=${savestop}
module_status ${i} -1 "" "${name}/${module} cannot run setBugDatabaseInfo from findbugs"
((result=result+1))
((i=i+1))
continue
fi
"${FINDBUGS_HOME}/bin/convertXmlToText" -html \
"${warnings_file}.xml" \
"${warnings_file}.html"
if [[ $? != 0 ]]; then
savestop=$(stop_clock)
MODULE_STATUS_TIMER[${i}]=${savestop}
module_status ${i} -1 "" "${name}/${module} cannot run convertXmlToText from findbugs"
((result=result+1))
fi
if [[ -z ${FINDBUGS_VERSION}
&& ${name} == branch ]]; then
FINDBUGS_VERSION=$(${GREP} -i "BugCollection version=" "${warnings_file}.xml" \
| cut -f2 -d\" \
| cut -f1 -d\" )
if [[ -n ${FINDBUGS_VERSION} ]]; then
add_footer_table findbugs "v${FINDBUGS_VERSION}"
fi
fi
((i=i+1))
done
return ${result}
}
## @description Track pre-existing findbugs warnings
## @audience private
## @stability evolving
## @replaceable no
## @return 0 on success
## @return 1 on failure
function findbugs_preapply
{
declare fn
declare module
declare modindex=0
declare warnings_file
declare module_findbugs_warnings
declare result=0
declare msg
if ! verify_needed_test findbugs; then
return 0
fi
big_console_header "findbugs detection: ${PATCH_BRANCH}"
findbugs_runner branch
result=$?
if [[ ${UNSUPPORTED_TEST} = true ]]; then
return 0
fi
until [[ ${modindex} -eq ${#MODULE[@]} ]]; do
if [[ ${MODULE_STATUS[${modindex}]} == -1 ]]; then
((result=result+1))
((modindex=modindex+1))
continue
fi
module=${MODULE[${modindex}]}
start_clock
offset_clock "${MODULE_STATUS_TIMER[${modindex}]}"
fn=$(module_file_fragment "${module}")
warnings_file="${PATCH_DIR}/branch-findbugs-${fn}-warnings"
# shellcheck disable=SC2016
module_findbugs_warnings=$("${FINDBUGS_HOME}/bin/filterBugs" -first \
"${PATCH_BRANCH}" \
"${warnings_file}.xml" \
"${warnings_file}.xml" \
| ${AWK} '{print $1}')
if [[ ${module_findbugs_warnings} -gt 0 ]] ; then
msg="${module} in ${PATCH_BRANCH} has ${module_findbugs_warnings} extant Findbugs warnings."
if [[ "${FINDBUGS_WARNINGS_FAIL_PRECHECK}" = "true" ]]; then
module_status ${modindex} -1 "branch-findbugs-${fn}-warnings.html" "${msg}"
((result=result+1))
elif [[ "${BUILDMODE}" = full ]]; then
module_status ${modindex} -1 "branch-findbugs-${fn}-warnings.html" "${msg}"
((result=result+1))
populate_test_table FindBugs "module:${module}"
#shellcheck disable=SC2162
while read line; do
firstpart=$(echo "${line}" | cut -f2 -d:)
secondpart=$(echo "${line}" | cut -f9- -d' ')
add_test_table "" "${firstpart}:${secondpart}"
done < <("${FINDBUGS_HOME}/bin/convertXmlToText" "${warnings_file}.xml")
else
module_status ${modindex} 0 "branch-findbugs-${fn}-warnings.html" "${msg}"
fi
fi
savestop=$(stop_clock)
MODULE_STATUS_TIMER[${modindex}]=${savestop}
((modindex=modindex+1))
done
modules_messages branch findbugs true
if [[ ${result} != 0 ]]; then
return 1
fi
return 0
}
## @description Verify patch does not trigger any findbugs warnings
## @audience private
## @stability evolving
## @replaceable no
## @return 0 on success
## @return 1 on failure
function findbugs_postinstall
{
declare module
declare fn
declare combined_xml
declare branchxml
declare patchxml
declare newbugsbase
declare fixedbugsbase
declare branch_warnings
declare patch_warnings
declare fixed_warnings
declare line
declare firstpart
declare secondpart
declare i=0
declare result=0
declare savestop
declare summarize=true
declare statstring
if ! verify_needed_test findbugs; then
return 0
fi
big_console_header "findbugs detection: ${BUILDMODE}"
findbugs_runner patch
if [[ ${UNSUPPORTED_TEST} = true ]]; then
return 0
fi
until [[ $i -eq ${#MODULE[@]} ]]; do
if [[ ${MODULE_STATUS[${i}]} == -1 ]]; then
((result=result+1))
((i=i+1))
continue
fi
start_clock
offset_clock "${MODULE_STATUS_TIMER[${i}]}"
module="${MODULE[${i}]}"
buildtool_cwd "${i}"
fn=$(module_file_fragment "${module}")
combined_xml="${PATCH_DIR}/combined-findbugs-${fn}.xml"
branchxml="${PATCH_DIR}/branch-findbugs-${fn}-warnings.xml"
patchxml="${PATCH_DIR}/patch-findbugs-${fn}-warnings.xml"
if [[ -f "${branchxml}" ]]; then
# shellcheck disable=SC2016
branch_warnings=$("${FINDBUGS_HOME}/bin/filterBugs" -first \
"${PATCH_BRANCH}" \
"${branchxml}" \
"${branchxml}" \
| ${AWK} '{print $1}')
else
branchxml=${patchxml}
fi
newbugsbase="${PATCH_DIR}/new-findbugs-${fn}"
fixedbugsbase="${PATCH_DIR}/fixed-findbugs-${fn}"
"${FINDBUGS_HOME}/bin/computeBugHistory" -useAnalysisTimes -withMessages \
-output "${combined_xml}" \
"${branchxml}" \
"${patchxml}"
if [[ $? != 0 ]]; then
popd >/dev/null
module_status ${i} -1 "" "${module} cannot run computeBugHistory from findbugs"
((result=result+1))
savestop=$(stop_clock)
MODULE_STATUS_TIMER[${i}]=${savestop}
((i=i+1))
continue
fi
# shellcheck disable=SC2016
patch_warnings=$("${FINDBUGS_HOME}/bin/filterBugs" -first \
"patch" \
"${patchxml}" \
"${patchxml}" \
| ${AWK} '{print $1}')
#shellcheck disable=SC2016
add_warnings=$("${FINDBUGS_HOME}/bin/filterBugs" -first patch \
"${combined_xml}" "${newbugsbase}.xml" | ${AWK} '{print $1}')
if [[ $? != 0 ]]; then
popd >/dev/null
module_status ${i} -1 "" "${module} cannot run filterBugs (#1) from findbugs"
((result=result+1))
savestop=$(stop_clock)
MODULE_STATUS_TIMER[${i}]=${savestop}
((i=i+1))
continue
fi
#shellcheck disable=SC2016
fixed_warnings=$("${FINDBUGS_HOME}/bin/filterBugs" -fixed patch \
"${combined_xml}" "${fixedbugsbase}.xml" | ${AWK} '{print $1}')
if [[ $? != 0 ]]; then
popd >/dev/null
module_status ${i} -1 "" "${module} cannot run filterBugs (#2) from findbugs"
((result=result+1))
savestop=$(stop_clock)
MODULE_STATUS_TIMER[${i}]=${savestop}
((i=i+1))
continue
fi
statstring=$(generic_calcdiff_status "${branch_warnings}" "${patch_warnings}" "${add_warnings}")
"${FINDBUGS_HOME}/bin/convertXmlToText" -html "${newbugsbase}.xml" \
"${newbugsbase}.html"
if [[ $? != 0 ]]; then
popd >/dev/null
module_status ${i} -1 "" "${module} cannot run convertXmlToText from findbugs"
((result=result+1))
savestop=$(stop_clock)
MODULE_STATUS_TIMER[${i}]=${savestop}
((i=i+1))
continue
fi
if [[ ${add_warnings} -gt 0 ]] ; then
populate_test_table FindBugs "module:${module}"
#shellcheck disable=SC2162
while read line; do
firstpart=$(echo "${line}" | cut -f2 -d:)
secondpart=$(echo "${line}" | cut -f9- -d' ')
add_test_table "" "${firstpart}:${secondpart}"
done < <("${FINDBUGS_HOME}/bin/convertXmlToText" "${newbugsbase}.xml")
module_status ${i} -1 "new-findbugs-${fn}.html" "${module} ${statstring}"
((result=result+1))
elif [[ ${fixed_warnings} -gt 0 ]]; then
module_status ${i} +1 "" "${module} ${statstring}"
summarize=false
fi
savestop=$(stop_clock)
MODULE_STATUS_TIMER[${i}]=${savestop}
popd >/dev/null
((i=i+1))
done
modules_messages patch findbugs "${summarize}"
if [[ ${result} != 0 ]]; then
return 1
fi
return 0
}
function findbugs_rebuild
{
declare repostatus=$1
if [[ "${repostatus}" = branch || "${BUILDMODE}" = full ]]; then
findbugs_preapply
else
findbugs_postinstall
fi
}