mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00

Was only getting coverage for packages with test files. Instead, include packages that don't have test files as well.
345 lines
10 KiB
Bash
Executable File
345 lines
10 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# Run all etcd tests
|
|
# ./test
|
|
# ./test -v
|
|
#
|
|
# Run tests for one package
|
|
#
|
|
# PKG=./wal ./test
|
|
# PKG=snap ./test
|
|
#
|
|
# Run code coverage
|
|
# COVERDIR must either be a absolute path or a relative path to the etcd root
|
|
# COVERDIR=coverage PASSES="build_cov cov" ./test
|
|
set -e
|
|
|
|
source ./build
|
|
|
|
# build tests with vendored dependencies
|
|
etcd_setup_gopath
|
|
|
|
if [ -z "$PASSES" ]; then
|
|
PASSES="fmt dep compile build unit"
|
|
fi
|
|
|
|
# Invoke ./cover for HTML output
|
|
COVER=${COVER:-"-cover"}
|
|
|
|
# Hack: gofmt ./ will recursively check the .git directory. So use *.go for gofmt.
|
|
IGNORE_PKGS="(cmd|vendor|etcdserverpb|rafttest|gopath.proto)"
|
|
INTEGRATION_PKGS="(integration|e2e|contrib|functional-tester)"
|
|
|
|
# all github.com/coreos/etcd/whatever pkgs that are not auto-generated / tools
|
|
PKGS=`find . -name \*.go | while read a; do dirname $a; done | sort | uniq | egrep -v "$IGNORE_PKGS" | egrep -v "(tools/|contrib/|e2e|pb)" | sed "s|\.|${REPO_PATH}|g"`
|
|
# pkg1,pkg2,pkg3
|
|
PKGS_COMMA=`echo ${PKGS} | sed 's/ /,/g'`
|
|
|
|
TEST_PKGS=`find . -name \*_test.go | while read a; do dirname $a; done | sort | uniq | egrep -v "$IGNORE_PKGS" | sed "s|\./||g"`
|
|
FORMATTABLE=`find . -name \*.go | while read a; do echo $(dirname $a)/"*.go"; done | sort | uniq | egrep -v "$IGNORE_PKGS" | sed "s|\./||g"`
|
|
TESTABLE_AND_FORMATTABLE=`echo "$TEST_PKGS" | egrep -v "$INTEGRATION_PKGS"`
|
|
|
|
# TODO: 'client' pkg fails with gosimple from generated files
|
|
# TODO: 'rafttest' is failing with unused
|
|
STATIC_ANALYSIS_PATHS=`find . -name \*.go | while read a; do dirname $a; done | sort | uniq | egrep -v "$IGNORE_PKGS" | grep -v 'client'`
|
|
|
|
if [ -z "$GOARCH" ]; then
|
|
GOARCH=$(go env GOARCH);
|
|
fi
|
|
|
|
# user has not provided PKG override
|
|
if [ -z "$PKG" ]; then
|
|
TEST=$TESTABLE_AND_FORMATTABLE
|
|
FMT=$FORMATTABLE
|
|
|
|
# user has provided PKG override
|
|
else
|
|
# strip out leading dotslashes and trailing slashes from PKG=./foo/
|
|
TEST=${PKG/#./}
|
|
TEST=${TEST/#\//}
|
|
TEST=${TEST/%\//}
|
|
|
|
# only run gofmt on packages provided by user
|
|
FMT="$TEST"
|
|
fi
|
|
|
|
# split TEST into an array and prepend REPO_PATH to each local package
|
|
split=(${TEST// / })
|
|
TEST=${split[@]/#/${REPO_PATH}/}
|
|
|
|
# determine whether target supports race detection
|
|
if [ "$GOARCH" == "amd64" ]; then
|
|
RACE="--race"
|
|
fi
|
|
|
|
function unit_pass {
|
|
echo "Running unit tests..."
|
|
# only -run=Test so examples can run in integration tests
|
|
go test -timeout 3m ${COVER} ${RACE} -cpu 1,2,4 -run=Test $@ ${TEST}
|
|
}
|
|
|
|
function integration_pass {
|
|
echo "Running integration tests..."
|
|
go test -timeout 15m -v -cpu 1,2,4 $@ ${REPO_PATH}/integration
|
|
go test -timeout 1m -v ${RACE} -cpu 1,2,4 $@ ${REPO_PATH}/client/integration
|
|
go test -timeout 10m -v ${RACE} -cpu 1,2,4 $@ ${REPO_PATH}/clientv3/integration
|
|
go test -timeout 1m -v -cpu 1,2,4 $@ ${REPO_PATH}/contrib/raftexample
|
|
go test -timeout 1m -v ${RACE} -cpu 1,2,4 -run=Example $@ ${TEST}
|
|
}
|
|
|
|
function cov_pass {
|
|
echo "Running code coverage..."
|
|
# install gocovmerge before running code coverage from github.com/wadey/gocovmerge
|
|
# gocovmerge merges coverage files
|
|
if ! which gocovmerge >/dev/null; then
|
|
echo "gocovmerge not installed"
|
|
exit 255
|
|
fi
|
|
|
|
if [ -z "$COVERDIR" ]; then
|
|
echo "COVERDIR undeclared"
|
|
exit 255
|
|
fi
|
|
|
|
if [ ! -f "bin/etcd_test" ]; then
|
|
echo "etcd_test binary not found"
|
|
exit 255
|
|
fi
|
|
|
|
mkdir -p "$COVERDIR"
|
|
|
|
# run code coverage for unit and integration tests
|
|
for t in `echo "${TEST_PKGS}" | egrep -v "(e2e|functional-tester)"`; do
|
|
tf=`echo $t | tr / _`
|
|
# cache package compilation data for faster repeated builds
|
|
go test -covermode=set -coverpkg $PKGS_COMMA -i -v ${REPO_PATH}/$t
|
|
# uses -run=Test to skip examples because clientv3/ example tests will leak goroutines
|
|
go test -covermode=set -coverpkg $PKGS_COMMA -timeout 15m -run=Test -v -coverprofile "$COVERDIR/${tf}.coverprofile" ${REPO_PATH}/$t
|
|
done
|
|
|
|
# run code coverage for e2e tests
|
|
# use 30m timeout because e2e coverage takes longer
|
|
# due to many tests cause etcd process to wait
|
|
# on leadership transfer timeout during gracefully shutdown
|
|
go test -tags cov -timeout 30m -v ${REPO_PATH}"/e2e"
|
|
|
|
gocovmerge "$COVERDIR"/*.coverprofile >"$COVERDIR"/cover.out
|
|
}
|
|
|
|
function e2e_pass {
|
|
echo "Running e2e tests..."
|
|
go test -timeout 15m -v -cpu 1,2,4 $@ ${REPO_PATH}/e2e
|
|
}
|
|
|
|
function integration_e2e_pass {
|
|
echo "Running integration and e2e tests..."
|
|
|
|
go test -timeout 15m -v -cpu 1,2,4 $@ ${REPO_PATH}/e2e &
|
|
e2epid="$!"
|
|
go test -timeout 15m -v -cpu 1,2,4 $@ ${REPO_PATH}/integration &
|
|
intpid="$!"
|
|
wait $e2epid
|
|
wait $intpid
|
|
go test -timeout 1m -v ${RACE} -cpu 1,2,4 $@ ${REPO_PATH}/client/integration
|
|
go test -timeout 10m -v ${RACE} -cpu 1,2,4 $@ ${REPO_PATH}/clientv3/integration
|
|
go test -timeout 1m -v -cpu 1,2,4 $@ ${REPO_PATH}/contrib/raftexample
|
|
go test -timeout 1m -v ${RACE} -cpu 1,2,4 -run=Example $@ ${TEST}
|
|
}
|
|
|
|
function grpcproxy_pass {
|
|
go test -timeout 15m -v ${RACE} -tags cluster_proxy -cpu 1,2,4 $@ ${REPO_PATH}/integration
|
|
go test -timeout 15m -v ${RACE} -tags cluster_proxy -cpu 1,2,4 $@ ${REPO_PATH}/clientv3/integration
|
|
}
|
|
|
|
function release_pass {
|
|
rm -f ./bin/etcd-last-release
|
|
# to grab latest patch release; bump this up for every minor release
|
|
UPGRADE_VER=$(git tag -l --sort=-version:refname "v3.1.*" | head -1)
|
|
if [ -n "$MANUAL_VER" ]; then
|
|
# in case, we need to test against different version
|
|
UPGRADE_VER=$MANUAL_VER
|
|
fi
|
|
|
|
local file="etcd-$UPGRADE_VER-linux-$GOARCH.tar.gz"
|
|
echo "Downloading $file"
|
|
|
|
set +e
|
|
curl --fail -L https://github.com/coreos/etcd/releases/download/$UPGRADE_VER/$file -o /tmp/$file
|
|
local result=$?
|
|
set -e
|
|
case $result in
|
|
0) ;;
|
|
22) return 0
|
|
;;
|
|
*) exit $result
|
|
;;
|
|
esac
|
|
|
|
tar xzvf /tmp/$file -C /tmp/ --strip-components=1
|
|
mkdir -p ./bin
|
|
mv /tmp/etcd ./bin/etcd-last-release
|
|
}
|
|
|
|
function fmt_pass {
|
|
toggle_failpoints disable
|
|
|
|
echo "Checking gofmt..."
|
|
fmtRes=$(gofmt -l -s -d $FMT)
|
|
if [ -n "${fmtRes}" ]; then
|
|
echo -e "gofmt checking failed:\n${fmtRes}"
|
|
exit 255
|
|
fi
|
|
|
|
echo "Checking govet..."
|
|
vetRes=$(go vet $TEST)
|
|
if [ -n "${vetRes}" ]; then
|
|
echo -e "govet checking failed:\n${vetRes}"
|
|
exit 255
|
|
fi
|
|
|
|
echo "Checking 'go tool vet -shadow'..."
|
|
for path in $FMT; do
|
|
if [ "${path##*.}" != "go" ]; then
|
|
path="${path}/*.go"
|
|
fi
|
|
vetRes=$(go tool vet -shadow ${path})
|
|
if [ -n "${vetRes}" ]; then
|
|
echo -e "govet -shadow checking ${path} failed:\n${vetRes}"
|
|
exit 255
|
|
fi
|
|
done
|
|
|
|
echo "Checking documentation style..."
|
|
# eschew you
|
|
yous=`find . -name \*.md | xargs egrep --color "[Yy]ou[r]?[ '.,;]" | grep -v /v2/ || true`
|
|
if [ ! -z "$yous" ]; then
|
|
echo -e "found 'you' in documentation:\n${yous}"
|
|
exit 255
|
|
fi
|
|
|
|
if which goword >/dev/null; then
|
|
echo "Checking goword..."
|
|
# get all go files to process
|
|
gofiles=`find $FMT -iname '*.go' 2>/dev/null`
|
|
# ignore tests and protobuf files
|
|
gofiles=`echo ${gofiles} | sort | uniq | sed "s/ /\n/g" | egrep -v "(\\_test.go|\\.pb\\.go)"`
|
|
# only check for broken exported godocs
|
|
gowordRes=`goword -use-spell=false ${gofiles} | grep godoc-export | sort`
|
|
if [ ! -z "$gowordRes" ]; then
|
|
echo -e "goword checking failed:\n${gowordRes}"
|
|
exit 255
|
|
fi
|
|
else
|
|
echo "Skipping goword..."
|
|
fi
|
|
|
|
if which gosimple >/dev/null; then
|
|
echo "Checking gosimple..."
|
|
simplResult=`gosimple ${STATIC_ANALYSIS_PATHS} 2>&1 || true`
|
|
if [ -n "${simplResult}" ]; then
|
|
echo -e "gosimple checking failed:\n${simplResult}"
|
|
exit 255
|
|
fi
|
|
else
|
|
echo "Skipping gosimple..."
|
|
fi
|
|
|
|
if which unused >/dev/null; then
|
|
echo "Checking unused..."
|
|
unusedResult=`unused ${STATIC_ANALYSIS_PATHS} 2>&1 || true`
|
|
if [ -n "${unusedResult}" ]; then
|
|
echo -e "unused checking failed:\n${unusedResult}"
|
|
exit 255
|
|
fi
|
|
else
|
|
echo "Skipping unused..."
|
|
fi
|
|
|
|
if which staticcheck >/dev/null; then
|
|
echo "Checking staticcheck..."
|
|
staticcheckResult=`staticcheck ${STATIC_ANALYSIS_PATHS} 2>&1 || true`
|
|
if [ ! -n "${staticcheckResult}" ]; then
|
|
continue
|
|
fi
|
|
# TODO: resolve these after go1.8 migration
|
|
# See https://github.com/dominikh/go-tools/tree/master/cmd/staticcheck
|
|
STATIC_CHECK_MASK="SA(1016|1019|2002)"
|
|
if egrep -v "$STATIC_CHECK_MASK" "${staticcheckResult}"; then
|
|
echo -e "staticcheck checking ${path} failed:\n${staticcheckResult}"
|
|
exit 255
|
|
else
|
|
echo -e "staticcheck warning:\n${staticcheckResult}"
|
|
fi
|
|
else
|
|
echo "Skipping staticcheck..."
|
|
fi
|
|
|
|
echo "Checking for license header..."
|
|
licRes=$(for file in $(find . -type f -iname '*.go' ! -path './cmd/*' ! -path './gopath.proto/*'); do
|
|
head -n3 "${file}" | grep -Eq "(Copyright|generated|GENERATED)" || echo -e " ${file}"
|
|
done;)
|
|
if [ -n "${licRes}" ]; then
|
|
echo -e "license header checking failed:\n${licRes}"
|
|
exit 255
|
|
fi
|
|
|
|
echo "Checking commit titles..."
|
|
git log --oneline `git merge-base HEAD master`...HEAD | while read l; do
|
|
commitMsg=`echo "$l" | cut -f2- -d' '`
|
|
if [[ "$commitMsg" == Merge* ]]; then
|
|
# ignore "Merge pull" commits
|
|
continue
|
|
fi
|
|
if [[ "$commitMsg" == Revert* ]]; then
|
|
# ignore revert commits
|
|
continue
|
|
fi
|
|
|
|
pkgPrefix=`echo "$commitMsg" | cut -f1 -d':'`
|
|
spaceCommas=`echo "$commitMsg" | sed 's/ /\n/g' | grep -c ',$' || echo 0`
|
|
commaSpaces=`echo "$commitMsg" | sed 's/,/\n/g' | grep -c '^ ' || echo 0`
|
|
if [[ `echo $commitMsg | grep -c ":..*"` == 0 || "$commitMsg" == "$pkgPrefix" || "$spaceCommas" != "$commaSpaces" ]]; then
|
|
echo "$l"...
|
|
echo "Expected commit title format '<package>{\", \"<package>}: <description>'"
|
|
echo "Got: $l"
|
|
exit 255
|
|
fi
|
|
done
|
|
}
|
|
|
|
function dep_pass {
|
|
echo "Checking package dependencies..."
|
|
# don't pull in etcdserver package
|
|
pushd clientv3 >/dev/null
|
|
badpkg="(etcdserver|mvcc)"
|
|
deps=`go list -f '{{ .Deps }}' | sed 's/ /\n/g' | egrep "${badpkg}" | egrep -v "${badpkg}/" || echo ""`
|
|
popd >/dev/null
|
|
if [ ! -z "$deps" ]; then
|
|
echo -e "clientv3 has masked dependencies:\n${deps}"
|
|
exit 255
|
|
fi
|
|
}
|
|
|
|
function build_cov_pass {
|
|
out="bin"
|
|
if [ -n "${BINDIR}" ]; then out="${BINDIR}"; fi
|
|
go test -c -covermode=set -coverpkg=$PKGS_COMMA -o ${out}/etcd_test
|
|
go test -tags cov -c -covermode=set -coverpkg=$PKGS_COMMA -o ${out}/etcdctl_test ${REPO_PATH}/etcdctl
|
|
}
|
|
|
|
function compile_pass {
|
|
echo "Checking build..."
|
|
go build -v ./tools/...
|
|
}
|
|
|
|
# fail fast on static tests
|
|
function build_pass {
|
|
GO_BUILD_FLAGS="-a -v" etcd_build
|
|
}
|
|
|
|
for pass in $PASSES; do
|
|
${pass}_pass $@
|
|
done
|
|
|
|
echo "Success"
|