From fd65c752c8f03acb3a70ab2686d3f1838e97ea21 Mon Sep 17 00:00:00 2001 From: Matthew Sykes Date: Mon, 8 Jan 2018 13:17:51 -0500 Subject: [PATCH] [FAB-7649] refactor unit test script Change-Id: Id179b886d958bac8338bc2ef2fc7bdcc6c4759af Signed-off-by: Matthew Sykes --- unit-test/run.sh | 201 ++++++++++++++++++++++++++--------------------- 1 file changed, 113 insertions(+), 88 deletions(-) diff --git a/unit-test/run.sh b/unit-test/run.sh index cd336f8e48a..09fbe206aa9 100755 --- a/unit-test/run.sh +++ b/unit-test/run.sh @@ -1,98 +1,123 @@ -#!/bin/bash +#!/bin/bash -e # # Copyright IBM Corp. All Rights Reserved. # # SPDX-License-Identifier: Apache-2.0 # +# regexes for packages to exclude from unit test +excluded_packages=( + "github.com/hyperledger/fabric/bccsp/factory" # this package's tests need to be mocked + "github.com/hyperledger/fabric/bccsp/mocks" + "github.com/hyperledger/fabric/bddtests" + "github.com/hyperledger/fabric/build/" + "github.com/hyperledger/fabric/common/ledger/testutil" + "github.com/hyperledger/fabric/common/mocks" + "github.com/hyperledger/fabric/core/chaincode/platforms/car/test" # until FAB-7629 is resolved + "github.com/hyperledger/fabric/core/deliverservice/mocks" + "github.com/hyperledger/fabric/core/ledger/kvledger/example" + "github.com/hyperledger/fabric/core/ledger/kvledger/marble_example" + "github.com/hyperledger/fabric/core/ledger/testutil" + "github.com/hyperledger/fabric/core/mocks" + "github.com/hyperledger/fabric/core/testutil" + "github.com/hyperledger/fabric/examples" + "github.com/hyperledger/fabric/orderer/mocks" + "github.com/hyperledger/fabric/orderer/sample_clients" + "github.com/hyperledger/fabric/test" + "github.com/hyperledger/fabric/vendor/" +) -set -e -ARCH=`uname -m` - -#check job type, do patch set specific unit test when job is verify -if [ "$JOB_TYPE" = "VERIFY" ]; then - - cd $GOPATH/src/github.com/hyperledger/fabric/ - - #figure out what packages should be tested for uncommitted changes - # first check for uncommitted changes - TEST_PKGS=$(git diff --name-only HEAD * | grep .go$ | grep -v ^vendor/ \ - | grep -v ^build/ | sed 's%/[^/]*$%/%'| sort -u \ - | awk '{print "github.com/hyperledger/fabric/"$1"..."}') - - if [ -z "$TEST_PKGS" ]; then - # next check for changes in the latest commit - typically this will - # be for CI only, but could also handle a committed change before - # pushing to Gerrit - TEST_PKGS=$(git diff-tree --no-commit-id --name-only -r $(git log -2 \ - --pretty=format:"%h") | grep .go$ | grep -v ^vendor/ | grep -v ^build/ \ - | sed 's%/[^/]*$%/%'| sort -u | \ - awk '{print "github.com/hyperledger/fabric/"$1"..."}') - fi - - #only run the test when test pkgs is not empty - if [[ ! -z "$TEST_PKGS" ]]; then - echo "Testing packages:" - echo $TEST_PKGS - echo " with tags " $GO_TAGS - # use go test -cover as this is much more efficient than gocov - time go test -cover -tags "$GO_TAGS" -ldflags "$GO_LDFLAGS" $TEST_PKGS -short -timeout=20m - else - echo "Nothing changed in unit test!!!" - fi - -else - - #check to see if TEST_PKGS is set else use default (all packages) - TEST_PKGS=${TEST_PKGS:-github.com/hyperledger/fabric/...} - echo -n "Obtaining list of tests to run for the following packages: ${TEST_PKGS}" - - # Some examples and packages don't play nice with `go test` - PKGS=`go list ${TEST_PKGS} 2> /dev/null | \ - grep -v /vendor/ | \ - grep -v /build/ | \ - grep -v /bccsp/mocks | \ - grep -v /bddtests | \ - grep -v /orderer/mocks | \ - grep -v /orderer/sample_clients | \ - grep -v /common/mocks | \ - grep -v /common/ledger/testutil | \ - grep -v /core/mocks | \ - grep -v /core/testutil | \ - grep -v /core/ledger/testutil | \ - grep -v /core/ledger/kvledger/example | \ - grep -v /core/ledger/kvledger/marble_example | \ - grep -v /core/deliverservice/mocks | \ - # this package's tests need to be mocked - grep -v /bccsp/factory | \ - grep -v github.com/hyperledger/fabric/gossip | \ - grep -v /test | \ - grep -v /examples` - - if [ x$ARCH == xppc64le -o x$ARCH == xs390x ]; then - PKGS=`echo $PKGS | sed 's@'github.com/hyperledger/fabric/core/chaincode/platforms/java/test'@@g'` - PKGS=`echo $PKGS | sed 's@'github.com/hyperledger/fabric/core/chaincode/platforms/java'@@g'` - fi - - echo -e "\nDONE!" - echo -e "Running tests with tags ${GO_TAGS} ..." - - if [ "$JOB_TYPE" = "PROFILE" ]; then +# regexes for packages that must be run serially +serial_packages=( + "github.com/hyperledger/fabric/gossip" +) + +# obtain packages changed since some git refspec +packages_diff() { + local ref="${1:-HEAD}" + + git -C "${GOPATH}/src/github.com/hyperledger/fabric" diff --no-commit-id --name-only -r "${1:-HEAD}" | + grep -Ev '.go$|^vendor/|^build/' | \ + sed 's%/[^/]*$%/%' | sort -u | \ + awk '{print "github.com/hyperledger/fabric/"$1"..."}' +} + +# "go list" packages and filter out excluded packages +list_and_filter() { + go list $@ 2>/dev/null | grep -Ev $(local IFS='|' ; echo "${excluded_packages[*]}") || true +} + +# remove packages that must be tested serially +parallel_test_packages() { + echo "$@" | grep -Ev $(local IFS='|' ; echo "${serial_packages[*]}") || true +} + +# get packages that must be tested serially +serial_test_packages() { + echo "$@" | grep -E $(local IFS='|' ; echo "${serial_packages[*]}") || true +} + +# "go test" the provided packages. Packages that are not prsent in the serial package list +# will be tested in parallel +run_tests() { + local parallel=$(parallel_test_packages "$@") + if [ -n "${parallel}" ]; then + time go test -cover -tags "$GO_TAGS" -ldflags "$GO_LDFLAGS" ${parallel[@]} -short -timeout=20m + fi + + local serial=$(serial_test_packages "$@") + if [ -n "${serial}" ]; then + time go test -cover -tags "$GO_TAGS" -ldflags "$GO_LDFLAGS" ${serial[@]} -short -p 1 -timeout=20m + fi +} + +# "go test" the provided packages and generate code coverage reports. Until go 1.10 is released, +# profile reports can only be generated one package at a time. +run_tests_with_coverage() { # Initialize profile.cov - date echo "mode: set" > profile.cov - for pkg in $PKGS - do - :> profile_tmp.cov - go test -cover -coverprofile=profile_tmp.cov -tags "$GO_TAGS" -ldflags "$GO_LDFLAGS" $pkg -timeout=20m - tail -n +2 profile_tmp.cov >> profile.cov || echo "Unable to append coverage for $pkg" + for pkg in "$@"; do + :> profile_tmp.cov + go test -cover -coverprofile=profile_tmp.cov -tags "$GO_TAGS" -ldflags "$GO_LDFLAGS" $pkg -timeout=20m + tail -n +2 profile_tmp.cov >> profile.cov || echo "Unable to append coverage for $pkg" done - #convert to cobertura format - gocov convert profile.cov |gocov-xml > report.xml - date - else - time go test -cover -tags "$GO_TAGS" -ldflags "$GO_LDFLAGS" $PKGS -short -timeout=20m - # gossip packages need to be serialized - time go test -cover -tags "$GO_TAGS" -ldflags "$GO_LDFLAGS" ./gossip/... -short -p 1 -timeout=20m - fi -fi + + # convert to cobertura format + gocov convert profile.cov | gocov-xml > report.xml +} + +main() { + # default behavior is to run all tests + local package_spec=${TEST_PKGS:-github.com/hyperledger/fabric/...} + + # extra exclusions for ppc and s390x + local arch=`uname -m` + if [ x${arch} == xppc64le -o x${arch} == xs390x ]; then + excluded_packages+=("github.com/hyperledger/fabric/core/chaincode/platforms/java") + fi + + # when running a "verify" job, only test packages that have changed + if [ "${JOB_TYPE}" = "VERIFY" ]; then + # first check for uncommitted changes + package_spec=$(packages_diff HEAD) + if [ -z "${package_spec}" ]; then + # next check for changes in the latest commit - typically this will + # be for CI only, but could also handle a committed change before + # pushing to Gerrit + package_spec=$(packages_diff HEAD^) + fi + fi + + # expand the package spec into an array of packages + local -a packages=$(list_and_filter ${package_spec}) + + if [ -z "${packages}" ]; then + echo "Nothing to test!!!" + elif [ "${JOB_TYPE}" = "PROFILE" ]; then + run_tests_with_coverage "${packages[@]}" + else + run_tests "${packages[@]}" + fi +} + +main