244 lines
6.5 KiB
Bash
Executable File
244 lines
6.5 KiB
Bash
Executable File
#!/bin/bash
|
|
# Run all tests and coverage checks. Called from Travis automatically, also
|
|
# suitable to run manually. See list of prerequisite packages in .travis.yml
|
|
if type realpath >/dev/null 2>&1 ; then
|
|
cd $(realpath $(dirname $0))
|
|
fi
|
|
|
|
FAILURE=0
|
|
|
|
TESTPATHS=$(go list -f '{{ .ImportPath }}' ./...)
|
|
|
|
# We need to know, for github-pr-status, what the triggering commit is.
|
|
# Assume first it's the travis commit (for builds of master), unless we're
|
|
# a PR, when it's actually the first parent.
|
|
TRIGGER_COMMIT=${TRAVIS_COMMIT}
|
|
if [ "x${TRAVIS_PULL_REQUEST}" != "x" ] ; then
|
|
revs=$(git rev-list --parents -n 1 HEAD)
|
|
# The trigger commit is the last ID in the space-delimited rev-list
|
|
TRIGGER_COMMIT=${revs##* }
|
|
fi
|
|
|
|
GITHUB_SECRET_FILE="$(pwd)/test/github-secret.json"
|
|
|
|
start_context() {
|
|
CONTEXT="$1"
|
|
printf "[%16s] Starting\n" ${CONTEXT}
|
|
}
|
|
|
|
end_context() {
|
|
printf "[%16s] Done\n" ${CONTEXT}
|
|
CONTEXT=""
|
|
}
|
|
|
|
update_status() {
|
|
if ([ "${TRAVIS}" == "true" ] && [ "x${CONTEXT}" != "x" ]) && [ -f "${GITHUB_SECRET_FILE}" ]; then
|
|
github-pr-status --authfile $GITHUB_SECRET_FILE \
|
|
--owner "letsencrypt" --repo "boulder" \
|
|
status --sha "${TRIGGER_COMMIT}" --context "${CONTEXT}" \
|
|
--url "https://travis-ci.org/letsencrypt/boulder/builds/${TRAVIS_BUILD_ID}" $*
|
|
fi
|
|
}
|
|
|
|
function run() {
|
|
echo "$@"
|
|
"$@" 2>&1
|
|
local status=$?
|
|
|
|
if [ ${status} -eq 0 ]; then
|
|
update_status --state success
|
|
echo "Success: $@"
|
|
else
|
|
FAILURE=1
|
|
update_status --state failure
|
|
echo "[!] FAILURE: $@"
|
|
fi
|
|
|
|
return ${status}
|
|
}
|
|
|
|
function run_and_comment() {
|
|
if [ "x${TRAVIS}" = "x" ] || [ "${TRAVIS_PULL_REQUEST}" == "false" ] || [ ! -f "${GITHUB_SECRET_FILE}" ] ; then
|
|
run "$@"
|
|
else
|
|
result=$(run "$@")
|
|
local status=$?
|
|
# Only send a comment if exit code > 0
|
|
if [ ${status} -ne 0 ] ; then
|
|
echo $'```\n'${result}$'\n```' | github-pr-status --authfile $GITHUB_SECRET_FILE \
|
|
--owner "letsencrypt" --repo "boulder" \
|
|
comment --pr "${TRAVIS_PULL_REQUEST}" -b -
|
|
fi
|
|
fi
|
|
}
|
|
|
|
function die() {
|
|
if [ ! -z "$1" ]; then
|
|
echo $1 > /dev/stderr
|
|
fi
|
|
exit 1
|
|
}
|
|
|
|
function build_letsencrypt() {
|
|
# Test for python 2 installs with the usual names.
|
|
if hash python2 2>/dev/null; then
|
|
PY=python2
|
|
elif hash python2.7 2>/dev/null; then
|
|
PY=python2.7
|
|
else
|
|
die "unable to find a python2 or python2.7 binary in \$PATH"
|
|
fi
|
|
|
|
run git clone \
|
|
https://www.github.com/letsencrypt/letsencrypt.git \
|
|
$LETSENCRYPT_PATH || exit 1
|
|
|
|
cd $LETSENCRYPT_PATH
|
|
|
|
run virtualenv --no-site-packages -p $PY ./venv
|
|
run ./venv/bin/pip install -r requirements.txt -e acme -e . -e letsencrypt-apache -e letsencrypt-nginx
|
|
|
|
cd -
|
|
}
|
|
|
|
function run_unit_tests() {
|
|
if [ "${TRAVIS}" == "true" ]; then
|
|
# Run each test by itself for Travis, so we can get coverage
|
|
for path in ${TESTPATHS}; do
|
|
dir=$(basename $path)
|
|
run go test -race -cover -coverprofile=${dir}.coverprofile ${path}
|
|
done
|
|
|
|
# Gather all the coverprofiles
|
|
[ -e $GOBIN/gover ] && run $GOBIN/gover
|
|
|
|
# We don't use the run function here because sometimes goveralls fails to
|
|
# contact the server and exits with non-zero status, but we don't want to
|
|
# treat that as a failure.
|
|
[ -e $GOBIN/goveralls ] && $GOBIN/goveralls -coverprofile=gover.coverprofile -service=travis-ci
|
|
else
|
|
# Run all the tests together if local, for speed
|
|
run go test $GOTESTFLAGS ./...
|
|
fi
|
|
}
|
|
|
|
# Path for installed go package binaries. If yours is different, override with
|
|
# GOBIN=/my/path/to/bin ./test.sh
|
|
GOBIN=${GOBIN:-$HOME/gopath/bin}
|
|
|
|
#
|
|
# Run Go Vet, a correctness-focused static analysis tool
|
|
#
|
|
|
|
start_context "test/vet"
|
|
run_and_comment go vet ./...
|
|
end_context #test/vet
|
|
|
|
#
|
|
# Run Go Lint, a style-focused static analysis tool
|
|
#
|
|
|
|
start_context "test/golint"
|
|
[ -x "$(which golint)" ] && run golint ./...
|
|
end_context #test/golint
|
|
|
|
#
|
|
# Ensure all files are formatted per the `go fmt` tool
|
|
#
|
|
start_context "test/gofmt"
|
|
check_gofmt() {
|
|
unformatted=$(find . -name "*.go" -not -path "./Godeps/*" -print | xargs -n1 gofmt -l)
|
|
if [ "x${unformatted}" == "x" ] ; then
|
|
return 0
|
|
else
|
|
V="Unformatted files found.
|
|
Please run 'go fmt' on each of these files and amend your commit to continue."
|
|
|
|
for f in ${unformatted}; do
|
|
V=$(printf "%s\n - %s" "${V}" "${f}")
|
|
done
|
|
|
|
# Print to stdout
|
|
printf "%s\n\n" "${V}"
|
|
[ "${TRAVIS}" == "true" ] || exit 1 # Stop here if running locally
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
run_and_comment check_gofmt
|
|
end_context #test/gofmt
|
|
|
|
if [ "${TRAVIS}" == "true" ]; then
|
|
./test/create_db.sh || die "unable to create the boulder database with test/create_db.sh"
|
|
fi
|
|
|
|
#
|
|
# Unit Tests. These do not receive a context or status updates,
|
|
# as they are reflected in our eventual exit code.
|
|
#
|
|
|
|
if [ "${SKIP_UNIT_TESTS}" == "1" ]; then
|
|
echo "Skipping unit tests."
|
|
else
|
|
run_unit_tests
|
|
fi
|
|
|
|
# If the unittests failed, exit before trying to run the integration test.
|
|
if [ ${FAILURE} != 0 ]; then
|
|
echo "--------------------------------------------------"
|
|
echo "--- A unit test or tool failed. ---"
|
|
echo "--- Stopping before running integration tests. ---"
|
|
echo "--------------------------------------------------"
|
|
exit ${FAILURE}
|
|
fi
|
|
|
|
if [ "${SKIP_INTEGRATION_TESTS}" = "1" ]; then
|
|
echo "Skipping integration tests."
|
|
exit ${FAILURE}
|
|
fi
|
|
|
|
#
|
|
# Integration tests
|
|
#
|
|
|
|
# Set context to integration, and force a pending state
|
|
start_context "test/integration"
|
|
update_status --state pending --description "Integration Tests in progress"
|
|
|
|
if [ -z "$LETSENCRYPT_PATH" ]; then
|
|
LETSENCRYPT_PATH=$(mktemp -d -t leXXXX)
|
|
echo "------------------------------------------------"
|
|
echo "--- Checking out letsencrypt client is slow. ---"
|
|
echo "--- Recommend setting \$LETSENCRYPT_PATH to ---"
|
|
echo "--- client repo with initialized virtualenv ---"
|
|
echo "------------------------------------------------"
|
|
build_letsencrypt
|
|
elif [ ! -d "${LETSENCRYPT_PATH}" ]; then
|
|
build_letsencrypt
|
|
fi
|
|
|
|
source $LETSENCRYPT_PATH/venv/bin/activate || die "The LETSENCRYPT_PATH (${LETSENCRYPT_PATH}) does not have a venv/bin/activate and probably did not build correctly."
|
|
export LETSENCRYPT_PATH
|
|
|
|
python test/amqp-integration-test.py
|
|
case $? in
|
|
0) # Success
|
|
update_status --state success
|
|
;;
|
|
1) # Python client failed
|
|
update_status --state success --description "Python integration failed."
|
|
FAILURE=1
|
|
;;
|
|
2) # Node client failed
|
|
update_status --state failure --description "NodeJS integration failed."
|
|
FAILURE=1
|
|
;;
|
|
*) # Error occurred
|
|
update_status --state error --description "Unknown error occurred."
|
|
FAILURE=1
|
|
;;
|
|
esac
|
|
end_context #test/integration
|
|
|
|
exit ${FAILURE}
|