Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitaly.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacob Vosmaer (GitLab) <jacob@gitlab.com>2018-03-06 18:46:20 +0300
committerZeger-Jan van de Weg <zegerjan@gitlab.com>2018-03-06 18:46:20 +0300
commitd78c86c3b61b97e42b6cab098b736c0f4b983e13 (patch)
treedfb37922f33b96a7047791eee1f9ae27fee2f880
parent50437ca090895d9cb131c6714ebf08da77041642 (diff)
Make 'make cover' faster
-rw-r--r--Makefile7
-rw-r--r--_support/test-cover-parallel.go110
2 files changed, 111 insertions, 6 deletions
diff --git a/Makefile b/Makefile
index aaa9165e5..490e230fd 100644
--- a/Makefile
+++ b/Makefile
@@ -172,12 +172,7 @@ cover: prepare-tests $(GOCOVMERGE)
@echo "NOTE: make cover does not exit 1 on failure, don't use it to check for tests success!"
mkdir -p "$(COVERAGE_DIR)"
rm -f $(COVERAGE_DIR)/*.out "$(COVERAGE_DIR)/all.merged" "$(COVERAGE_DIR)/all.html"
- echo $(LOCAL_PACKAGES) > $(TARGET_DIR)/local_packages
- for MOD in `cat $(TARGET_DIR)/local_packages`; do \
- go test -coverpkg=`cat $(TARGET_DIR)/local_packages |tr " " "," ` \
- -coverprofile=$(COVERAGE_DIR)/unit-`echo $$MOD|tr "/" "_"`.out \
- $$MOD 2>&1 | grep -v "no packages being tested depend on"; \
- done
+ go run _support/test-cover-parallel.go $(COVERAGE_DIR) $(LOCAL_PACKAGES)
$(GOCOVMERGE) $(COVERAGE_DIR)/*.out > "$(COVERAGE_DIR)/all.merged"
go tool cover -html "$(COVERAGE_DIR)/all.merged" -o "$(COVERAGE_DIR)/all.html"
@echo ""
diff --git a/_support/test-cover-parallel.go b/_support/test-cover-parallel.go
new file mode 100644
index 000000000..2719f6d3c
--- /dev/null
+++ b/_support/test-cover-parallel.go
@@ -0,0 +1,110 @@
+package main
+
+import (
+ "fmt"
+ "log"
+ "os"
+ "os/exec"
+ "strings"
+ "sync"
+ "time"
+)
+
+const (
+ progName = "test-cover-parallel.go"
+)
+
+func main() {
+ if len(os.Args) <= 2 {
+ log.Fatalf("usage %s OUT_DIR PKG [PKG...]", progName)
+ }
+
+ outDir := os.Args[1]
+ packages := os.Args[2:]
+
+ if err := buildDependentPackages(packages); err != nil {
+ log.Fatal(err)
+ }
+
+ numWorkers := 2
+ cmdChan := make(chan *exec.Cmd)
+ wg := &sync.WaitGroup{}
+ for i := 0; i < numWorkers; i++ {
+ wg.Add(1)
+ go func() {
+ for cmd := range cmdChan {
+ runCover(cmd)
+ }
+ wg.Done()
+ }()
+ }
+
+ packageMap := make(map[string]bool, len(packages))
+ for _, pkg := range packages {
+ packageMap[pkg] = true
+ }
+
+ for _, pkg := range packages {
+ deps, err := depsForPackage(pkg, packageMap)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ args := []string{
+ "go",
+ "test",
+ fmt.Sprintf("-coverpkg=%s", strings.Join(deps, ",")),
+ fmt.Sprintf("-coverprofile=%s/unit-%s.out", outDir, strings.Replace(pkg, "/", "_", -1)),
+ pkg,
+ }
+
+ cmdChan <- exec.Command(args[0], args[1:]...)
+ }
+ close(cmdChan)
+
+ wg.Wait()
+}
+
+func depsForPackage(pkg string, packageMap map[string]bool) ([]string, error) {
+ depsOut, err := exec.Command("go", "list", "-f", `{{ join .Deps "\n" }}`, pkg).Output()
+ if err != nil {
+ return nil, err
+ }
+
+ deps := []string{pkg}
+ for _, d := range strings.Split(string(depsOut), "\n") {
+ if packageMap[d] {
+ deps = append(deps, d)
+ }
+ }
+
+ return deps, nil
+}
+
+func buildDependentPackages(packages []string) error {
+ buildDeps := exec.Command("go", append([]string{"test", "-i"}, packages...)...)
+ buildDeps.Stdout = os.Stdout
+ buildDeps.Stderr = os.Stderr
+ start := time.Now()
+ if err := buildDeps.Run(); err != nil {
+ log.Printf("command failed: %s", strings.Join(buildDeps.Args, " "))
+ return err
+ }
+ log.Printf("go test -i\t%.3fs", time.Since(start).Seconds())
+ return nil
+}
+
+func runCover(cmd *exec.Cmd) {
+ start := time.Now()
+ err := cmd.Run()
+ duration := time.Since(start)
+
+ status := fmt.Sprintf("%s\t%.3fs", cmd.Args[len(cmd.Args)-1], duration.Seconds())
+
+ if err != nil {
+ fmt.Printf("FAIL\t%s\n", status)
+ fmt.Printf("command was: %s\n", strings.Join(cmd.Args, " "))
+ } else {
+ fmt.Printf("ok \t%s\n", status)
+ }
+}