blob: 28019a33b6e4311343bf204d335746dfe12c27f2 [file] [log] [blame]
#!/bin/bash -e
# Copyright 2017 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# This script quickly builds the tast executable or its unit tests within a
# ChromeOS chroot.
if [ ! -f /etc/cros_chroot_version ]; then
echo "File /etc/cros_chroot_version not found. Are you in the chroot?"
exit 1
fi
# Personal Go workspace used to cache compiled packages.
readonly GOHOME="${HOME}/go"
# Directory where compiled packages are cached.
readonly PKGDIR="${GOHOME}/pkg"
# Go workspaces containing the Tast source.
readonly SRCDIRS=(
"${HOME}/chromiumos/src/platform/tast"
"${HOME}/chromiumos/src/platform/tast-tests"
"${HOME}/chromiumos/src/platform/tast-tests-private"
"${HOME}/chromiumos/src/platform/tests-partners/partner-intel-private"
)
# Package to build to produce tast executables.
readonly TAST_PKG="go.chromium.org/tast/core/cmd/tast"
# Output filename for tast executable.
readonly TAST_OUT="${GOHOME}/bin/tast"
# Readonly Go workspaces containing source to build. Note that the packages
# installed to /usr/lib/gopath (dev-go/crypto, dev-go/subcommand, etc.) need to
# be emerged beforehand.
export GOPATH="$(IFS=:; echo "${SRCDIRS[*]}"):/usr/lib/gopath"
export GO111MODULE=off # enforce GOPATH mode
# Disable cgo and PIE on building Tast binaries. See:
# https://crbug.com/976196
# https://github.com/golang/go/issues/30986#issuecomment-475626018
export CGO_ENABLED=0
export GOPIE=0
readonly CMD=$(basename "${0}")
# Prints usage information and exits.
usage() {
cat - <<EOF >&2
Quickly builds the tast executable or its unit tests.
Usage:
${CMD} Builds tast to
${CMD//?/ } ${TAST_OUT}.
${CMD} -d Builds tast with
${CMD//?/ } debugging symbols to
${CMD//?/ } ${TAST_OUT}.
${CMD} -b <pkg> -o <path> Builds <pkg> to <path>.
${CMD} [-v] -T [-- <gotest opts>] Tests all packages.
${CMD} [-v] [-r <regex>] -t <pkg> [-- <gotest opts>] Tests <pkg>.
${CMD} [-v] -G [-f] [-- <gotest opts>] Tests all packages
and generates code
coverage reports
to ${PWD}
/coverage_results.
${CMD} [-v] [-r <regex>] -g <pkg> [-- <gotest opts>] Tests <pkg> and generates
code coverage for
the <pkg> to
${PWD}
/coverage_results.
${CMD} -C Checks all code using
${CMD//?/ } "go vet".
${CMD} -c <pkg> Checks <pkg>'s code.
EOF
exit 1
}
# Prints all packages containing a file with the given suffix.
get_pkgs_with_file_suffix() {
local suffix="$1"
local dir
for dir in "${SRCDIRS[@]}"; do
if [[ -d "${dir}/src" ]]; then
(cd "${dir}/src"
find -L . -name "*${suffix}" -exec dirname {} + | sort | uniq | cut -b 3-)
fi
done
}
# Prints all checkable packages.
get_check_pkgs() {
get_pkgs_with_file_suffix ".go"
}
# Prints all testable packages.
get_test_pkgs() {
get_pkgs_with_file_suffix "_test.go"
}
# Builds an executable package to a destination path.
run_build() {
local pkg="${1}"
local dest="${2}"
if [[ "${debug}" == 0 ]]; then
go build -pkgdir "${PKGDIR}" -o "${dest}" "${pkg}"
else
go build -gcflags="all=-N -l" -pkgdir "${PKGDIR}" -o "${dest}" "${pkg}"
fi
}
# Checks one or more packages.
run_vet() {
go vet -unusedresult.funcs=errors.New,errors.Wrap,errors.Wrapf,fmt.Errorf,\
fmt.Sprint,fmt.Sprintf,sort.Reverse \
-printf.funcs=Log,Logf,Error,Errorf,Fatal,Fatalf,Wrap,Wrapf "${@}"
}
# Tests one or more packages.
run_test() {
local args=("${@}" "${EXTRAARGS[@]}")
go test "${verbose_flag[@]}" -pkgdir "${PKGDIR}" \
${test_regex:+"-run=${test_regex}"} "${args[@]}"
}
# Tests and generates code coverage for one or more packages.
# Code coverage directory format:
# coverage_result/
# YYYY-MM-DD_HH:MM:SS/
# tast_func_coverage_all.txt or tast_func_coverage_<pkg>.txt
# tast_code_coverage_all.html or tast_code_coverage_<pkg>.html
# tast_code_coverage_all.out or tast_code_coverage_<pkg>.out
run_code_coverage() {
local args=("${@}" "${EXTRAARGS[@]}")
local curr_time
curr_time="$(date '+%Y-%m-%d_%H:%M:%S')"
local dir="coverage_result/${curr_time}"
mkdir -p "${dir}"
local pkg_name
if [ ${#args[@]} -gt 1 ]; then
pkg_name="all"
else
pkg_name="${args[0]//\//_}"
fi
go test "${verbose_flag[@]}" -covermode=atomic -pkgdir "${PKGDIR}" \
${test_regex:+"-run=${test_regex}"} "${args[@]}" \
-coverprofile="${dir}/tast_code_coverage_${pkg_name}.out"
go tool cover -html="${dir}/tast_code_coverage_${pkg_name}.out" \
-o "${dir}/tast_code_coverage_${pkg_name}.html"
go tool cover -func="${dir}/tast_code_coverage_${pkg_name}.out" -o \
"${dir}/tast_func_coverage_${pkg_name}.txt"
}
# Executable package to build.
build_pkg=
# Path to which executable package should be installed.
build_out=
# Package to check via "go vet".
check_pkg=
# Test package to build and run.
test_pkg=
# Test package to build, run, and generate code coverage data.
code_coverage_pkg=
# Verbose flag for testing.
verbose_flag=()
# Test regex list for unit testing.
test_regex=
# Whether to build and run a debug package.
debug=0
while getopts "CTGdb:c:ho:r:t:g:v-" opt; do
case "${opt}" in
C)
check_pkg=all
;;
T)
test_pkg=all
;;
G)
code_coverage_pkg=all
;;
d)
debug=1
;;
b)
build_pkg="${OPTARG}"
;;
c)
check_pkg="${OPTARG}"
;;
o)
build_out="${OPTARG}"
;;
r)
test_regex="${OPTARG}"
;;
t)
test_pkg="${OPTARG}"
;;
g)
code_coverage_pkg="${OPTARG}"
;;
v)
verbose_flag=(-v)
;;
*)
usage
;;
esac
done
shift $((OPTIND-1))
EXTRAARGS=( "$@" )
if [ -n "${build_pkg}" ]; then
if [ -z "${build_out}" ]; then
echo "Required output file missing: -o <path>" >&2
exit 1
fi
run_build "${build_pkg}" "${build_out}"
elif [ -n "${test_pkg}" ]; then
if [ "${test_pkg}" = 'all' ]; then
# mapfile reads output from get_test_pkgs into array
mapfile -t test_pkgs < <(get_test_pkgs)
run_test "${test_pkgs[@]}"
else
run_test "${test_pkg}"
fi
elif [ -n "${code_coverage_pkg}" ]; then
if [ "${code_coverage_pkg}" = 'all' ]; then
# mapfile reads output from get_test_pkgs into array
mapfile -t test_pkgs < <(get_test_pkgs)
run_code_coverage "${test_pkgs[@]}"
else
run_code_coverage "${code_coverage_pkg}"
fi
elif [ -n "${check_pkg}" ]; then
if [ "${check_pkg}" = 'all' ]; then
# mapfile reads output from get_check_pkgs into array
mapfile -t check_pkgs < <(get_check_pkgs)
run_vet "${check_pkgs[@]}"
else
run_vet "${check_pkg}"
fi
else
run_build "${TAST_PKG}" "${TAST_OUT}"
fi