mirror of https://github.com/apache/cassandra
Merge 663a84c1ce into 10557d7ffe
This commit is contained in:
commit
55c96670b0
|
|
@ -17,6 +17,25 @@
|
||||||
|
|
||||||
# temporary between CASSANDRA-18133 and CASSANDRA-18594
|
# temporary between CASSANDRA-18133 and CASSANDRA-18594
|
||||||
|
|
||||||
|
print_help() {
|
||||||
|
echo "Usage: $0 [-c|--clean] [-s|--summary] [-h|--help]"
|
||||||
|
echo " -c, --clean Remove locally created artifacts (ant clean) before building"
|
||||||
|
echo " -s, --summary Print a summary of failures instead of the full ant output"
|
||||||
|
echo " -h, --help Print help"
|
||||||
|
}
|
||||||
|
|
||||||
|
# arguments, with defaults
|
||||||
|
clean=false
|
||||||
|
summary=false
|
||||||
|
while [ "$#" -gt 0 ]; do
|
||||||
|
case "$1" in
|
||||||
|
-c|--clean) clean=true; shift ;;
|
||||||
|
-s|--summary) summary=true; shift ;;
|
||||||
|
-h|--help) print_help; exit 0 ;;
|
||||||
|
*) echo >&2 "Unknown argument $1"; print_help >&2; exit 1 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
# variables, with defaults
|
# variables, with defaults
|
||||||
[ "x${CASSANDRA_DIR}" != "x" ] || CASSANDRA_DIR="$(readlink -f $(dirname -- "$0")/..)"
|
[ "x${CASSANDRA_DIR}" != "x" ] || CASSANDRA_DIR="$(readlink -f $(dirname -- "$0")/..)"
|
||||||
|
|
||||||
|
|
@ -25,6 +44,18 @@ command -v ant >/dev/null 2>&1 || { echo >&2 "ant needs to be installed"; exit 1
|
||||||
[ -d "${CASSANDRA_DIR}" ] || { echo >&2 "Directory ${CASSANDRA_DIR} must exist"; exit 1; }
|
[ -d "${CASSANDRA_DIR}" ] || { echo >&2 "Directory ${CASSANDRA_DIR} must exist"; exit 1; }
|
||||||
[ -f "${CASSANDRA_DIR}/build.xml" ] || { echo >&2 "${CASSANDRA_DIR}/build.xml must exist"; exit 1; }
|
[ -f "${CASSANDRA_DIR}/build.xml" ] || { echo >&2 "${CASSANDRA_DIR}/build.xml must exist"; exit 1; }
|
||||||
|
|
||||||
|
# run ant, summarizing failures when --summary (summary exit code mirrors the build)
|
||||||
|
run_ant() {
|
||||||
|
if ${summary}; then
|
||||||
|
ant -f "${CASSANDRA_DIR}/build.xml" "$@" 2>&1 | "${CASSANDRA_DIR}/.build/sh/ant-log-summary.py" -
|
||||||
|
else
|
||||||
|
ant -f "${CASSANDRA_DIR}/build.xml" "$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# execute
|
# execute
|
||||||
ant -f "${CASSANDRA_DIR}/build.xml" jar
|
if ${clean}; then
|
||||||
|
run_ant clean
|
||||||
|
fi
|
||||||
|
run_ant jar
|
||||||
exit $?
|
exit $?
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,22 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
print_help() {
|
||||||
|
echo "Usage: $0 [-s|--summary] [-h|--help]"
|
||||||
|
echo " -s, --summary Print a summary of failures instead of the full ant output"
|
||||||
|
echo " -h, --help Print help"
|
||||||
|
}
|
||||||
|
|
||||||
|
# arguments, with defaults
|
||||||
|
summary=false
|
||||||
|
while [ "$#" -gt 0 ]; do
|
||||||
|
case "$1" in
|
||||||
|
-s|--summary) summary=true; shift ;;
|
||||||
|
-h|--help) print_help; exit 0 ;;
|
||||||
|
*) echo >&2 "Unknown argument $1"; print_help >&2; exit 1 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
# variables, with defaults
|
# variables, with defaults
|
||||||
[ "x${CASSANDRA_DIR}" != "x" ] || { CASSANDRA_DIR="$(dirname -- "$0")/.."; }
|
[ "x${CASSANDRA_DIR}" != "x" ] || { CASSANDRA_DIR="$(dirname -- "$0")/.."; }
|
||||||
|
|
||||||
|
|
@ -24,5 +40,12 @@ command -v ant >/dev/null 2>&1 || { echo >&2 "ant needs to be installed"; exit 1
|
||||||
[ -f "${CASSANDRA_DIR}/build.xml" ] || { echo >&2 "${CASSANDRA_DIR}/build.xml must exist"; exit 1; }
|
[ -f "${CASSANDRA_DIR}/build.xml" ] || { echo >&2 "${CASSANDRA_DIR}/build.xml must exist"; exit 1; }
|
||||||
|
|
||||||
# execute. memory needs to fit within the specified container size, see .jenkins/Jenkinsfile
|
# execute. memory needs to fit within the specified container size, see .jenkins/Jenkinsfile
|
||||||
ANT_OPTS="-Xmx2g -XX:+PrintClassHistogram -XX:OnOutOfMemoryError='kill -QUIT %p'" ant -f "${CASSANDRA_DIR}/build.xml" check # dependency-check # FIXME dependency-check now requires NVD key downloaded first
|
# dependency-check # FIXME dependency-check now requires NVD key downloaded first
|
||||||
|
export ANT_OPTS="-Xmx2g -XX:+PrintClassHistogram -XX:OnOutOfMemoryError='kill -QUIT %p'"
|
||||||
|
if ${summary}; then
|
||||||
|
# summarize failures; the summary's exit code mirrors the build
|
||||||
|
ant -f "${CASSANDRA_DIR}/build.xml" check 2>&1 | "${CASSANDRA_DIR}/.build/sh/ant-log-summary.py" -
|
||||||
|
else
|
||||||
|
ant -f "${CASSANDRA_DIR}/build.xml" check
|
||||||
|
fi
|
||||||
exit $?
|
exit $?
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,13 @@ set -o pipefail
|
||||||
# target types
|
# target types
|
||||||
TARGET_TYPES="build_dtest_jars stress-test fqltool-test sstableloader-test microbench microbench-test test-burn long-test cqlsh-test simulator-dtest test test-cdc test-compression test-oa test-system-keyspace-directory test-latest jvm-dtest jvm-dtest-upgrade jvm-dtest-novnode jvm-dtest-upgrade-novnode"
|
TARGET_TYPES="build_dtest_jars stress-test fqltool-test sstableloader-test microbench microbench-test test-burn long-test cqlsh-test simulator-dtest test test-cdc test-compression test-oa test-system-keyspace-directory test-latest jvm-dtest jvm-dtest-upgrade jvm-dtest-novnode jvm-dtest-upgrade-novnode"
|
||||||
|
|
||||||
# pre-conditions
|
error() {
|
||||||
|
echo >&2 $2;
|
||||||
|
set -x
|
||||||
|
exit $1
|
||||||
|
}
|
||||||
|
|
||||||
|
# pre-conditions (error() must be defined above)
|
||||||
command -v ant >/dev/null 2>&1 || { error 1 "ant needs to be installed"; }
|
command -v ant >/dev/null 2>&1 || { error 1 "ant needs to be installed"; }
|
||||||
command -v git >/dev/null 2>&1 || { error 1 "git needs to be installed"; }
|
command -v git >/dev/null 2>&1 || { error 1 "git needs to be installed"; }
|
||||||
command -v uuidgen >/dev/null 2>&1 || test -f /proc/sys/kernel/random/uuid || { error 1 "uuidgen needs to be installed"; }
|
command -v uuidgen >/dev/null 2>&1 || test -f /proc/sys/kernel/random/uuid || { error 1 "uuidgen needs to be installed"; }
|
||||||
|
|
@ -39,13 +45,6 @@ command -v uuidgen >/dev/null 2>&1 || test -f /proc/sys/kernel/random/uuid || {
|
||||||
[ -f "${CASSANDRA_DIR}/build.xml" ] || { error 1 "${CASSANDRA_DIR}/build.xml must exist"; }
|
[ -f "${CASSANDRA_DIR}/build.xml" ] || { error 1 "${CASSANDRA_DIR}/build.xml must exist"; }
|
||||||
[ -d "${DIST_DIR}" ] || { mkdir -p "${DIST_DIR}" ; }
|
[ -d "${DIST_DIR}" ] || { mkdir -p "${DIST_DIR}" ; }
|
||||||
|
|
||||||
|
|
||||||
error() {
|
|
||||||
echo >&2 $2;
|
|
||||||
set -x
|
|
||||||
exit $1
|
|
||||||
}
|
|
||||||
|
|
||||||
print_help() {
|
print_help() {
|
||||||
echo "Usage: $0 [-a|-t|-c|-e|-i|-b|-s|-h]"
|
echo "Usage: $0 [-a|-t|-c|-e|-i|-b|-s|-h]"
|
||||||
echo " -a Test target type: ${TARGET_TYPES}"
|
echo " -a Test target type: ${TARGET_TYPES}"
|
||||||
|
|
@ -54,13 +53,12 @@ print_help() {
|
||||||
echo " -b Specify the base git branch for comparison when determining changed tests to"
|
echo " -b Specify the base git branch for comparison when determining changed tests to"
|
||||||
echo " repeat. Defaults to ${BASE_BRANCH}. Note that this option is not used when"
|
echo " repeat. Defaults to ${BASE_BRANCH}. Note that this option is not used when"
|
||||||
echo " the '-a' option is specified."
|
echo " the '-a' option is specified."
|
||||||
echo " -s Skip automatic detection of changed tests. Useful when you need to repeat a few ones,"
|
|
||||||
echo " or when there are too many changed tests the CI env to handle."
|
|
||||||
echo " -e <key=value> Environment variables to be used in the repeated runs:"
|
echo " -e <key=value> Environment variables to be used in the repeated runs:"
|
||||||
echo " -e REPEATED_TESTS_STOP_ON_FAILURE=false"
|
echo " -e REPEATED_TESTS_STOP_ON_FAILURE=false"
|
||||||
echo " -e REPEATED_TESTS_COUNT=500"
|
echo " -e REPEATED_TESTS_COUNT=500"
|
||||||
echo " If you want to specify multiple environment variables simply add multiple -e options."
|
echo " If you want to specify multiple environment variables simply add multiple -e options."
|
||||||
echo " -i Ignore unknown environment variables"
|
echo " -i Ignore unknown environment variables"
|
||||||
|
echo " -s Print a summary of failed tests instead of the full ant output"
|
||||||
echo " -h Print help"
|
echo " -h Print help"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -84,7 +82,8 @@ fi
|
||||||
env_vars=""
|
env_vars=""
|
||||||
has_env_vars=false
|
has_env_vars=false
|
||||||
check_env_vars=true
|
check_env_vars=true
|
||||||
detect_changed_tests=true
|
summary=false
|
||||||
|
|
||||||
while getopts "a:t:c:e:ib:shj:" opt; do
|
while getopts "a:t:c:e:ib:shj:" opt; do
|
||||||
case $opt in
|
case $opt in
|
||||||
a ) test_target="$OPTARG"
|
a ) test_target="$OPTARG"
|
||||||
|
|
@ -105,7 +104,7 @@ while getopts "a:t:c:e:ib:shj:" opt; do
|
||||||
;;
|
;;
|
||||||
i ) check_env_vars=false
|
i ) check_env_vars=false
|
||||||
;;
|
;;
|
||||||
s ) detect_changed_tests=false
|
s ) summary=true
|
||||||
;;
|
;;
|
||||||
h ) print_help
|
h ) print_help
|
||||||
exit 0
|
exit 0
|
||||||
|
|
@ -331,7 +330,15 @@ _run_microbench() {
|
||||||
local -r arch="$(uname -m)"
|
local -r arch="$(uname -m)"
|
||||||
local -r output_dir="${DIST_DIR}/test/output/${_target}/jdk${java_version}/${arch}/${_split_chunk//\//_}"
|
local -r output_dir="${DIST_DIR}/test/output/${_target}/jdk${java_version}/${arch}/${_split_chunk//\//_}"
|
||||||
|
|
||||||
|
# microbench produces JMH json, not JUnit xml, so generate-test-report has
|
||||||
|
# nothing to summarise. Emit a "failed ..." line (matched by
|
||||||
|
# test-log-summary.py) so a benchmark failure is not reported as a pass in
|
||||||
|
# -s mode, where errexit is disabled and the ant failure would be swallowed.
|
||||||
|
set +o errexit
|
||||||
ant $_target ${ANT_TEST_OPTS} -Dbuild.test.output.dir=${output_dir} -Dbenchmark.name="${benchmark_pattern}" -Dmaven.test.failure.ignore=true
|
ant $_target ${ANT_TEST_OPTS} -Dbuild.test.output.dir=${output_dir} -Dbenchmark.name="${benchmark_pattern}" -Dmaven.test.failure.ignore=true
|
||||||
|
local -r _ant_status=$?
|
||||||
|
set -o errexit
|
||||||
|
[[ ${_ant_status} -ne 0 ]] && echo "failed ${_target} ${_split_chunk}"
|
||||||
|
|
||||||
# Post-process jmh-result.json to add jdk and arch parameters
|
# Post-process jmh-result.json to add jdk and arch parameters
|
||||||
local jmh_result="${output_dir}/jmh-result.json"
|
local jmh_result="${output_dir}/jmh-result.json"
|
||||||
|
|
@ -357,7 +364,7 @@ _main() {
|
||||||
local -r split_chunk="${chunk:-1/1}" # Chunks formatted as "K/N" for the Kth chunk of N chunks
|
local -r split_chunk="${chunk:-1/1}" # Chunks formatted as "K/N" for the Kth chunk of N chunks
|
||||||
|
|
||||||
# check split_chunk is compatible with target (if not a regexp)
|
# check split_chunk is compatible with target (if not a regexp)
|
||||||
if [[ "${_split_chunk}" =~ ^\d+/\d+$ ]] && [[ "1/1" != "${split_chunk}" ]] ; then
|
if [[ "${split_chunk}" =~ ^[0-9]+/[0-9]+$ ]] && [[ "1/1" != "${split_chunk}" ]] ; then
|
||||||
case ${target} in
|
case ${target} in
|
||||||
"stress-test" | "fqltool-test" | "cqlsh-test" | "sstableloader-test")
|
"stress-test" | "fqltool-test" | "cqlsh-test" | "sstableloader-test")
|
||||||
echo "Target ${target} does not support splits."
|
echo "Target ${target} does not support splits."
|
||||||
|
|
@ -401,8 +408,12 @@ _main() {
|
||||||
[ -d ${TMP_DIR} ] || mkdir -p "${TMP_DIR}"
|
[ -d ${TMP_DIR} ] || mkdir -p "${TMP_DIR}"
|
||||||
export ANT_TEST_OPTS="-Dno-build-test=true -Dtmp.dir=${TMP_DIR} -Dbuild.test.output.dir=${DIST_DIR}/test/output/${target}"
|
export ANT_TEST_OPTS="-Dno-build-test=true -Dtmp.dir=${TMP_DIR} -Dbuild.test.output.dir=${DIST_DIR}/test/output/${target}"
|
||||||
|
|
||||||
# fresh virtualenv and test logs results everytime
|
# fresh virtualenv and test logs results everytime.
|
||||||
[[ "/" == "${DIST_DIR}" ]] || rm -rf "${DIST_DIR}/test/{html,output,logs,reports}"
|
# NB: braces are intentionally unquoted so brace-expansion produces the four
|
||||||
|
# paths; quoting them deletes a single literal '{html,output,logs,reports}'
|
||||||
|
# path (a no-op), leaving stale TEST-*.xml that generate-test-report would
|
||||||
|
# then merge into the summary.
|
||||||
|
[[ "/" == "${DIST_DIR}" ]] || rm -rf ${DIST_DIR}/test/{html,output,logs,reports}
|
||||||
|
|
||||||
# cheap trick to ensure dependency libraries are in place. allows us to stash only project specific build artifacts.
|
# cheap trick to ensure dependency libraries are in place. allows us to stash only project specific build artifacts.
|
||||||
# also recreate some of the non-build files we need
|
# also recreate some of the non-build files we need
|
||||||
|
|
@ -492,10 +503,30 @@ _main() {
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# merge all unit xml files into one, and print summary test numbers
|
# merge all unit xml files into one, and print summary test numbers.
|
||||||
ant -quiet -silent generate-test-report
|
# Pin the output/report dirs to DIST_DIR; otherwise the report scans ant's
|
||||||
|
# default ${basedir}/build/test/output and, when DIST_DIR is overridden,
|
||||||
|
# finds no results and reports a false pass.
|
||||||
|
ant -quiet -silent generate-test-report \
|
||||||
|
-Dbuild.test.output.dir="${DIST_DIR}/test/output" \
|
||||||
|
-Dbuild.test.report.dir="${DIST_DIR}/test/reports"
|
||||||
|
|
||||||
popd >/dev/null
|
popd >/dev/null
|
||||||
}
|
}
|
||||||
|
|
||||||
_main "$@"
|
if ${summary}; then
|
||||||
|
# Summarize the run: run-tests.sh keeps going past failing tests (ant still
|
||||||
|
# prints BUILD SUCCESSFUL), so the summary's exit code — derived from the
|
||||||
|
# test results — is what determines pass/fail here. stderr (where error()
|
||||||
|
# writes) is left untouched so setup failures stay visible.
|
||||||
|
# Disable errexit/pipefail so a non-zero _main doesn't pre-empt the summary.
|
||||||
|
set +o errexit +o pipefail
|
||||||
|
_main "$@" | "${CASSANDRA_DIR}/.build/sh/test-log-summary.py" -
|
||||||
|
main_status=${PIPESTATUS[0]}
|
||||||
|
summary_status=${PIPESTATUS[1]}
|
||||||
|
# a setup failure inside _main (error() exits non-zero) takes precedence
|
||||||
|
[[ ${main_status} -ne 0 ]] && exit ${main_status}
|
||||||
|
exit ${summary_status}
|
||||||
|
else
|
||||||
|
_main "$@"
|
||||||
|
fi
|
||||||
|
|
|
||||||
|
|
@ -1,70 +0,0 @@
|
||||||
#!/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.
|
|
||||||
|
|
||||||
#set -o xtrace
|
|
||||||
set -o errexit
|
|
||||||
set -o pipefail
|
|
||||||
set -o nounset
|
|
||||||
|
|
||||||
bin="$(cd "$(dirname "$0")" > /dev/null; pwd)"
|
|
||||||
home="$(cd "$bin/../.." > /dev/null; pwd)" # this script lives in .build/sh
|
|
||||||
|
|
||||||
usage() {
|
|
||||||
if [[ $# -gt 0 ]]; then
|
|
||||||
echo "$*" 1>&2
|
|
||||||
fi
|
|
||||||
cat <<EOF
|
|
||||||
Usage: $(basename "$0") (options)*
|
|
||||||
Options:
|
|
||||||
--no-checkstyle - runs with all checkstyle disabled
|
|
||||||
-h|--help - this help page
|
|
||||||
EOF
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
no_checkstyle=false
|
|
||||||
|
|
||||||
while [[ "$#" -gt 0 ]]; do
|
|
||||||
case "$1" in
|
|
||||||
--no-checkstyle)
|
|
||||||
no_checkstyle=true
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
-h|--help)
|
|
||||||
usage
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
usage "Unknown argument $1"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
# Switch to the project root so all commands work properly
|
|
||||||
cd "$home"
|
|
||||||
|
|
||||||
opts=(
|
|
||||||
-Dant.gen-doc.skip=true
|
|
||||||
-Drat.skip=true
|
|
||||||
)
|
|
||||||
|
|
||||||
if [ $no_checkstyle ]; then
|
|
||||||
ant -Dno-checkstyle=true "${opts[@]}" clean jar "$@" 2>&1 | "$bin"/ant-log-summary.py -
|
|
||||||
else
|
|
||||||
ant "${opts[@]}" clean jar checkstyle checkstyle-test "$@" 2>&1 | "$bin"/ant-log-summary.py -
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
#!/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.
|
|
||||||
|
|
||||||
#set -o xtrace
|
|
||||||
set -o errexit
|
|
||||||
set -o pipefail
|
|
||||||
set -o nounset
|
|
||||||
|
|
||||||
bin="$(cd "$(dirname "$0")" > /dev/null; pwd)"
|
|
||||||
home="$(cd "$bin/../.." > /dev/null; pwd)" # this script lives in .build/sh
|
|
||||||
|
|
||||||
# Switch to the project root so all commands work properly
|
|
||||||
cd "$home"
|
|
||||||
|
|
||||||
"$bin"/ci-test "$@" 2>&1 | "$bin"/ant-log-summary.py -
|
|
||||||
|
|
@ -1,149 +0,0 @@
|
||||||
#!/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.
|
|
||||||
|
|
||||||
#set -o xtrace
|
|
||||||
set -o errexit
|
|
||||||
set -o pipefail
|
|
||||||
set -o nounset
|
|
||||||
|
|
||||||
bin="$(cd "$(dirname "$0")" > /dev/null; pwd)"
|
|
||||||
home="$(cd "$bin/../.." > /dev/null; pwd)" # this script lives in .build/sh
|
|
||||||
|
|
||||||
# Switch to the project root so all commands work properly
|
|
||||||
cd "$home"
|
|
||||||
|
|
||||||
error() {
|
|
||||||
echo "ERROR: $*" 1>&2
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
usage() {
|
|
||||||
if [[ $# -gt 0 ]]; then
|
|
||||||
echo "$*" 1>&2
|
|
||||||
fi
|
|
||||||
cat <<EOF
|
|
||||||
Usage: $(basename "$0") [class name] (options)*
|
|
||||||
Options:
|
|
||||||
--cdc - runs with cdc enabled
|
|
||||||
--compression - run with compression enabled
|
|
||||||
--jvm-dtest-version|--dtest-version - which jvm-dtest version to use
|
|
||||||
--reuse - skip calling ant realclean
|
|
||||||
--tokens|--num-tokens - number of vnode tokens to use for jvm-dtest
|
|
||||||
-h|--help - this help page
|
|
||||||
EOF
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if [[ $# -eq 0 ]]; then
|
|
||||||
usage "Missing required arguments"
|
|
||||||
fi
|
|
||||||
|
|
||||||
class_name=""
|
|
||||||
task="testclasslist"
|
|
||||||
fresh_build=true
|
|
||||||
jvm_dtest_version=""
|
|
||||||
num_tokens=""
|
|
||||||
while [[ "$#" -gt 0 ]]; do
|
|
||||||
case "$1" in
|
|
||||||
--tokens|--num-tokens)
|
|
||||||
num_tokens="$2"
|
|
||||||
shift 2
|
|
||||||
;;
|
|
||||||
--cdc)
|
|
||||||
task="testclasslist-cdc"
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
--compression)
|
|
||||||
task="testclasslist-compression"
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
--reuse)
|
|
||||||
fresh_build=false
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
--jvm-dtest-version|--dtest-version)
|
|
||||||
jvm_dtest_version="$2"
|
|
||||||
shift 2
|
|
||||||
;;
|
|
||||||
-h|--help)
|
|
||||||
usage
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
if [[ -z "${class_name:-}" ]]; then
|
|
||||||
class_name="$1"
|
|
||||||
shift
|
|
||||||
else
|
|
||||||
usage "Unknown argument $1"
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
if [[ -z "${class_name:-}" ]]; then
|
|
||||||
usage "No class provided"
|
|
||||||
fi
|
|
||||||
# Is the class name valid?
|
|
||||||
if [[ "$class_name" =~ [:#$] ]]; then
|
|
||||||
error "Unexpected class name: $class_name. Illegal characters were detected: ':', '#', and '\$' are not allowed! ci-test only supports class names, and not references to methods."
|
|
||||||
fi
|
|
||||||
path="$(echo "$class_name" | tr '.' '/' ).java"
|
|
||||||
prefix="$( find test | grep "$path" | awk -F/ '{print $2}' )"
|
|
||||||
|
|
||||||
JAVA_VERSION=$(java -version 2>&1 | awk -F '"' '/version/ {print $2}' | awk -F. '{print $1}')
|
|
||||||
|
|
||||||
if [ "$JAVA_VERSION" -ge 11 ]; then
|
|
||||||
export CASSANDRA_USE_JDK11=true
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "${num_tokens:-}" ]; then
|
|
||||||
export CASSANDRA_DTEST_NUM_TOKENS="$num_tokens"
|
|
||||||
fi
|
|
||||||
|
|
||||||
opts=(
|
|
||||||
-Dant.gen-doc.skip=true
|
|
||||||
-Dno-checkstyle=true
|
|
||||||
-Dant.gen-doc.skip=true
|
|
||||||
-Drat.skip=true
|
|
||||||
)
|
|
||||||
if [[ -n "${jvm_dtest_version:-}" ]]; then
|
|
||||||
opts+=( "-Ddtest-api.version=$jvm_dtest_version" )
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$fresh_build" == true ]]; then
|
|
||||||
if [[ ! "$path" =~ distributed/upgrade ]]; then
|
|
||||||
ant "${opts[@]}" realclean
|
|
||||||
ant "${opts[@]}"
|
|
||||||
ant "${opts[@]}" generate-idea-files
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# cleanup logs so w/e is around are for this run
|
|
||||||
rm -rf build/test/logs || true
|
|
||||||
|
|
||||||
test_timeout=$(grep "name=\"test.$prefix.timeout\"" build.xml | awk -F'"' '{print $4}' || true)
|
|
||||||
if [ -z "$test_timeout" ]; then
|
|
||||||
test_timeout=$(grep 'name="test.timeout"' build.xml | awk -F'"' '{print $4}')
|
|
||||||
fi
|
|
||||||
if [[ "$fresh_build" == false ]]; then
|
|
||||||
opts+=(-Dno-build-test=true)
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$prefix" == "simulator" ]]; then
|
|
||||||
ant "${opts[@]}" test-simulator-dtest -Dtest.name="$(echo "$path" | awk -F'.' '{print $1}' | awk -F'/' '{print $NF}')"
|
|
||||||
else
|
|
||||||
ant "${opts[@]}" "$task" -Dtest.timeout="$test_timeout" -Dtest.classlistfile=<(echo "$path") -Dtest.classlistprefix="$prefix"
|
|
||||||
fi
|
|
||||||
|
|
@ -1,86 +0,0 @@
|
||||||
#!/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.
|
|
||||||
|
|
||||||
#set -o xtrace
|
|
||||||
set -o errexit
|
|
||||||
set -o pipefail
|
|
||||||
set -o nounset
|
|
||||||
|
|
||||||
bin="$(cd "$(dirname "$0")" > /dev/null; pwd)"
|
|
||||||
home="$(cd "$bin/../.." > /dev/null; pwd)" # this script lives in .build/sh
|
|
||||||
|
|
||||||
# Switch to the project root so all commands work properly
|
|
||||||
cd "$home"
|
|
||||||
|
|
||||||
usage() {
|
|
||||||
if [[ $# -gt 0 ]]; then
|
|
||||||
echo "$*" 1>&2
|
|
||||||
fi
|
|
||||||
cat <<EOF
|
|
||||||
Usage: $(basename "$0") [class name] (option)*
|
|
||||||
|
|
||||||
Options:
|
|
||||||
EOF
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
_main() {
|
|
||||||
local class_name=""
|
|
||||||
fresh_build=true
|
|
||||||
while [[ "$#" -gt 0 ]]; do
|
|
||||||
case "$1" in
|
|
||||||
--reuse)
|
|
||||||
fresh_build=false
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
-h|--help)
|
|
||||||
usage
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
if [[ -z "${class_name:-}" ]]; then
|
|
||||||
class_name="$1"
|
|
||||||
shift
|
|
||||||
else
|
|
||||||
usage "Unknown argument $1"
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
if [[ -z "${class_name:-}" ]]; then
|
|
||||||
usage "No class provided"
|
|
||||||
fi
|
|
||||||
|
|
||||||
path="$(echo "$class_name" | tr '.' '/' ).java"
|
|
||||||
|
|
||||||
if $fresh_build; then
|
|
||||||
if [[ ! "$path" =~ distributed/upgrade ]]; then
|
|
||||||
ant realclean && ant && ant generate-idea-files
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
counter=1
|
|
||||||
echo ">>> Running attempt $counter"
|
|
||||||
while "$bin"/ci-test "$class_name" --reuse; do
|
|
||||||
counter=$(( counter + 1 ))
|
|
||||||
echo ">>> Running attempt $counter"
|
|
||||||
done;
|
|
||||||
echo "Exited after $counter attempts"
|
|
||||||
}
|
|
||||||
|
|
||||||
_main "$@"
|
|
||||||
|
|
@ -0,0 +1,183 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
# Summarize the output of .build/run-tests.sh.
|
||||||
|
#
|
||||||
|
# Unlike ant-log-summary.py (which keys off ant's BUILD FAILED/SUCCESSFUL),
|
||||||
|
# run-tests.sh deliberately continues past failing tests, as ant still prints
|
||||||
|
# BUILD SUCCESSFUL with test failures.
|
||||||
|
#
|
||||||
|
# Failures are identified from the test results instead:
|
||||||
|
# - the "[Test Summary] Run: N, Failed: N, Errors: N, Skipped: N" line
|
||||||
|
# emitted by ant's generate-test-report target,
|
||||||
|
# - run-tests.sh's own "failed <prefix> <target> ..." lines,
|
||||||
|
# - "failure rate: X/Y" lines printed for repeated runs,
|
||||||
|
# - per-test "Testcase: <name>:\tFAILED / Caused an ERROR" markers from the
|
||||||
|
# brief JUnit formatter,
|
||||||
|
# - a compile/setup "BUILD FAILED" (with the [javac] errors).
|
||||||
|
#
|
||||||
|
# The exit code mirrors the outcome: non-zero if any failure signal is seen.
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
TEST_SUMMARY_RE = re.compile(
|
||||||
|
r"\[Test Summary\]\s*Run:\s*(\d+),\s*Failed:\s*(\d+),\s*Errors:\s*(\d+),\s*Skipped:\s*(\d+)"
|
||||||
|
)
|
||||||
|
FAILURE_RATE_RE = re.compile(r"failure rate:\s*(\d+)/(\d+)")
|
||||||
|
# run-tests.sh: echo "failed ${_target_prefix} ${_testlist_target} ..."
|
||||||
|
RUN_TESTS_FAILED_RE = re.compile(r"^failed\s+\S+")
|
||||||
|
# brief JUnit formatter: "Testcase: <name>:\tFAILED" / ":\tCaused an ERROR",
|
||||||
|
# optionally prefixed by an ant task tag such as "[junit] ".
|
||||||
|
TESTCASE_FAIL_RE = re.compile(r"^(?:\[[^\]]+\]\s*)?Testcase:\s.*\b(FAILED|Caused an ERROR)\b")
|
||||||
|
|
||||||
|
|
||||||
|
def parse_args():
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Summarize Apache Cassandra .build/run-tests.sh output"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"log_file",
|
||||||
|
nargs="?",
|
||||||
|
default="-",
|
||||||
|
help='Path to the run-tests.sh log (use "-" or omit to read from stdin)',
|
||||||
|
)
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
ANT_TAG_RE = re.compile(r"^\[[^\]]+\]\s*")
|
||||||
|
|
||||||
|
|
||||||
|
def _strip_tag(line):
|
||||||
|
"""Drop a leading ant task tag such as '[junit] ' or '[echo] '."""
|
||||||
|
return ANT_TAG_RE.sub("", line.strip())
|
||||||
|
|
||||||
|
|
||||||
|
def summarize(content):
|
||||||
|
"""Return (failed, lines) where failed is a bool and lines is the summary."""
|
||||||
|
lines = content.split("\n")
|
||||||
|
|
||||||
|
summaries = [] # [Test Summary] lines
|
||||||
|
failed_targets = [] # run-tests.sh "failed ..." lines
|
||||||
|
failure_rates = [] # "failure rate: X/Y" lines
|
||||||
|
failed_testcases = [] # per-test FAILED / ERROR markers
|
||||||
|
javac_errors = [] # compile errors, when a BUILD FAILED is present
|
||||||
|
|
||||||
|
build_failed = "BUILD FAILED" in content
|
||||||
|
|
||||||
|
for line in lines:
|
||||||
|
stripped = line.strip()
|
||||||
|
m = TEST_SUMMARY_RE.search(line)
|
||||||
|
if m:
|
||||||
|
run, failures, errors, skipped = (int(g) for g in m.groups())
|
||||||
|
summaries.append((_strip_tag(line), failures, errors))
|
||||||
|
continue
|
||||||
|
if RUN_TESTS_FAILED_RE.match(stripped):
|
||||||
|
failed_targets.append(stripped)
|
||||||
|
continue
|
||||||
|
m = FAILURE_RATE_RE.search(line)
|
||||||
|
if m:
|
||||||
|
failure_rates.append((stripped, int(m.group(1))))
|
||||||
|
continue
|
||||||
|
if TESTCASE_FAIL_RE.match(stripped):
|
||||||
|
failed_testcases.append(_strip_tag(line))
|
||||||
|
continue
|
||||||
|
if build_failed and "[javac]" in line and ("error:" in line or "errors" in line):
|
||||||
|
clean = line.replace("[javac]", "").strip()
|
||||||
|
if clean:
|
||||||
|
javac_errors.append(clean)
|
||||||
|
|
||||||
|
# decide pass/fail
|
||||||
|
failed = build_failed
|
||||||
|
for _, failures, errors in summaries:
|
||||||
|
if failures or errors:
|
||||||
|
failed = True
|
||||||
|
if failed_targets:
|
||||||
|
failed = True
|
||||||
|
for _, n in failure_rates:
|
||||||
|
if n:
|
||||||
|
failed = True
|
||||||
|
|
||||||
|
# build the summary output
|
||||||
|
out = []
|
||||||
|
if build_failed:
|
||||||
|
out.append("BUILD FAILED")
|
||||||
|
if javac_errors:
|
||||||
|
out.append("")
|
||||||
|
out.append("Compilation Errors:")
|
||||||
|
out.append("-" * 20)
|
||||||
|
out.extend(javac_errors)
|
||||||
|
|
||||||
|
if failed_testcases:
|
||||||
|
out.append("")
|
||||||
|
out.append("Failed tests:")
|
||||||
|
out.append("-" * 13)
|
||||||
|
# de-duplicate while preserving order
|
||||||
|
seen = set()
|
||||||
|
for tc in failed_testcases:
|
||||||
|
if tc not in seen:
|
||||||
|
seen.add(tc)
|
||||||
|
out.append(tc)
|
||||||
|
|
||||||
|
if failed_targets:
|
||||||
|
out.append("")
|
||||||
|
out.extend(failed_targets)
|
||||||
|
|
||||||
|
for line, _ in failure_rates:
|
||||||
|
out.append(line)
|
||||||
|
|
||||||
|
if summaries:
|
||||||
|
out.append("")
|
||||||
|
for line, _, _ in summaries:
|
||||||
|
out.append(line)
|
||||||
|
elif not build_failed and not failed:
|
||||||
|
# nothing ran a test report and nothing failed
|
||||||
|
out.append("No test summary found (nothing ran, or non-test target).")
|
||||||
|
|
||||||
|
if not failed and summaries:
|
||||||
|
out.append("")
|
||||||
|
out.append("TESTS PASSED")
|
||||||
|
|
||||||
|
return failed, out
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
args = parse_args()
|
||||||
|
|
||||||
|
try:
|
||||||
|
if args.log_file == "-":
|
||||||
|
content = sys.stdin.read()
|
||||||
|
else:
|
||||||
|
with open(args.log_file, "r") as f:
|
||||||
|
content = f.read()
|
||||||
|
except FileNotFoundError:
|
||||||
|
print(f"Error: Log file '{args.log_file}' not found")
|
||||||
|
sys.exit(2)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error reading log file: {e}")
|
||||||
|
sys.exit(2)
|
||||||
|
|
||||||
|
failed, out = summarize(content)
|
||||||
|
print("\n".join(out))
|
||||||
|
sys.exit(1 if failed else 0)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
29
AGENTS.md
29
AGENTS.md
|
|
@ -14,31 +14,38 @@ Apache Cassandra is a NoSQL distributed database. This is the official Git repos
|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
||||||
```bash
|
Prefer the `.build/*.sh` helper scripts over calling `ant` directly. See
|
||||||
.build/sh/ai-build # clean, build JAR, and run checkstyle (output is summarized)
|
[.build/README.md](./.build/README.md) for the full set.
|
||||||
```
|
|
||||||
|
|
||||||
Do NOT call `ant` directly — always use the `ai-*` wrapper scripts which handle log summarization and correct working directory.
|
```bash
|
||||||
|
.build/build-jars.sh -s # build the Cassandra JAR (runs `ant jar`)
|
||||||
|
.build/build-jars.sh -s --clean # clean first, then build. `-s` summarizes output, remove for verbose
|
||||||
|
```
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
- Do NOT run the entire test suite. Run only the specific test(s) relevant to your change.
|
- Do NOT run the entire test suite. Run only the specific test(s) relevant to your change.
|
||||||
|
- The project must be built first (e.g. `.build/build-jars.sh`).
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Run a single unit test class
|
# Run a single test class: -a is the test type, -t is a class-name regexp
|
||||||
.build/sh/ai-ci-test org.apache.cassandra.service.StorageServiceServerTest
|
.build/run-tests.sh -s -a test -t StorageServiceServerTest
|
||||||
```
|
```
|
||||||
|
|
||||||
- `ai-ci-test` does NOT support method-level filtering — it runs the entire test class.
|
- `-a` is the test type (`test`, `jvm-dtest`, `long-test`, …; run `.build/run-tests.sh -h` for the full list).
|
||||||
|
- `-t` matches the test class only, not individual methods.
|
||||||
|
- `-s`/`--summary` provides a concise list of failed tests, remove for the full ant output
|
||||||
- When fixing a bug, first create a regression test that reproduces the failure, then implement the fix and verify.
|
- When fixing a bug, first create a regression test that reproduces the failure, then implement the fix and verify.
|
||||||
- Provide test(s) coverage for all new or modified code.
|
- Provide test(s) coverage for all new or modified code.
|
||||||
|
|
||||||
## Linting and Code Checks
|
## Linting and Code Checks
|
||||||
|
|
||||||
`.build/sh/ai-build` includes checkstyle validation. There is no need to run checkstyle separately.
|
```bash
|
||||||
|
.build/check-code.sh -s # runs `ant check` (build + checkstyle + checkstyle-test). `-s` summarizes output, remove for verbose
|
||||||
|
```
|
||||||
|
|
||||||
## Code Style
|
## Code Style
|
||||||
Cassandra enforces style via Checkstyle (run via `.build/sh/ai-build`). The official style guide is at https://cassandra.apache.org/_/development/code_style.html. Always defer to it when in doubt.
|
Cassandra enforces style via Checkstyle (run via `.build/check-code.sh`). The official style guide is at https://cassandra.apache.org/_/development/code_style.html. Always defer to it when in doubt.
|
||||||
|
|
||||||
General style conventions:
|
General style conventions:
|
||||||
- 4-space indentation, no tabs.
|
- 4-space indentation, no tabs.
|
||||||
|
|
@ -51,10 +58,12 @@ General style conventions:
|
||||||
- Commit messages format. For example:
|
- Commit messages format. For example:
|
||||||
|
|
||||||
```
|
```
|
||||||
<One sentence description, usually Jira title or CHANGES.txt summary>
|
<One sentence description, usually Jira title or CHANGES.txt summary, no jira id>
|
||||||
|
|
||||||
<Optional lengthier description>
|
<Optional lengthier description>
|
||||||
|
|
||||||
|
patch by <Authors,>; reviewed by <Reviewers,> for CASSANDRA-#####
|
||||||
|
|
||||||
Assisted-by: AGENT_NAME:MODEL_VERSION
|
Assisted-by: AGENT_NAME:MODEL_VERSION
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue