#!/bin/bash set -e DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SLOW= NO_GO_GET=true TAGS= PARALLEL= RACE="-race -covermode=atomic" TIMEOUT=1m VERBOSE= usage() { echo "$0 [-slow] [-in-container foo] [-netgo] [-(no-)go-get] [-timeout 1m]" } while [ $# -gt 0 ]; do case "$1" in "-v") VERBOSE="-v" shift 1 ;; "-slow") SLOW=true shift 1 ;; "-no-race") RACE= shift 1 ;; "-no-go-get") NO_GO_GET=true shift 1 ;; "-go-get") NO_GO_GET= shift 1 ;; "-netgo") TAGS="netgo" shift 1 ;; "-tags") TAGS="$2" shift 2 ;; "-p") PARALLEL=true shift 1 ;; "-timeout") TIMEOUT=$2 shift 2 ;; *) usage exit 2 ;; esac done GO_TEST_ARGS=(-tags "${TAGS[@]}" -cpu 4 -timeout "$TIMEOUT" $VERBOSE) if [ -n "$SLOW" ] || [ -n "$CIRCLECI" ]; then SLOW=true fi if [ -n "$SLOW" ]; then GO_TEST_ARGS=("${GO_TEST_ARGS[@]}" ${RACE}) # shellcheck disable=SC2153 if [ -n "$COVERDIR" ]; then coverdir="$COVERDIR" else coverdir=$(mktemp -d coverage.XXXXXXXXXX) fi mkdir -p "$coverdir" fi fail=0 if [ -z "$TESTDIRS" ]; then # NB: Relies on paths being prefixed with './'. TESTDIRS=($(git ls-files -- '*_test.go' | grep -vE '^(vendor|experimental)/' | xargs -n1 dirname | sort -u | sed -e 's|^|./|')) else # TESTDIRS on the right side is not really an array variable, it # is just a string with spaces, but it is written like that to # shut up the shellcheck tool. TESTDIRS=($(for d in ${TESTDIRS[*]}; do echo "$d"; done)) fi # If running on circle, use the scheduler to work out what tests to run on what shard if [ -n "$CIRCLECI" ] && [ -z "$NO_SCHEDULER" ] && [ -x "$DIR/sched" ]; then PREFIX=$(go list -e ./ | sed -e 's/\//-/g') TESTDIRS=($(echo "${TESTDIRS[@]}" | "$DIR/sched" sched "$PREFIX-$CIRCLE_PROJECT_USERNAME-$CIRCLE_PROJECT_REPONAME-$CIRCLE_BUILD_NUM" "$CIRCLE_NODE_TOTAL" "$CIRCLE_NODE_INDEX")) echo "${TESTDIRS[@]}" fi PACKAGE_BASE=$(go list -e ./) run_test() { local dir=$1 if [ -z "$NO_GO_GET" ]; then go get -t -tags "${TAGS[@]}" "$dir" fi local GO_TEST_ARGS_RUN=("${GO_TEST_ARGS[@]}") if [ -n "$SLOW" ]; then local COVERPKGS COVERPKGS=$( ( go list "$dir" go list -f '{{join .Deps "\n"}}' "$dir" | grep -v "vendor" | grep "^$PACKAGE_BASE/" ) | paste -s -d, -) local output output=$(mktemp "$coverdir/unit.XXXXXXXXXX") local GO_TEST_ARGS_RUN=("${GO_TEST_ARGS[@]}" "-coverprofile=$output" "-coverpkg=$COVERPKGS") fi local START START=$(date +%s) if ! go test "${GO_TEST_ARGS_RUN[@]}" "$dir"; then fail=1 fi local END END=$(date +%s) local RUNTIME=$((END - START)) # Report test runtime when running on circle, to help scheduler if [ -n "$CIRCLECI" ] && [ -z "$NO_SCHEDULER" ] && [ -x "$DIR/sched" ]; then "$DIR/sched" time "$dir" "$RUNTIME" fi } for dir in "${TESTDIRS[@]}"; do if [ -n "$PARALLEL" ]; then run_test "$dir" & else run_test "$dir" fi done if [ -n "$PARALLEL" ]; then wait fi if [ -n "$SLOW" ] && [ -z "$COVERDIR" ]; then go get github.com/weaveworks/tools/cover cover "$coverdir"/* >profile.cov rm -rf "$coverdir" go tool cover -html=profile.cov -o=coverage.html go tool cover -func=profile.cov | tail -n1 fi exit $fail