gitech

Форк
0
/
gocovmerge.go 
118 строк · 3.1 Кб
1
// Copyright 2020 The Gitea Authors. All rights reserved.
2
// Copyright (c) 2015, Wade Simmons
3
// SPDX-License-Identifier: MIT
4

5
// gocovmerge takes the results from multiple `go test -coverprofile` runs and
6
// merges them into one profile
7

8
//go:build ignore
9

10
package main
11

12
import (
13
	"flag"
14
	"fmt"
15
	"io"
16
	"log"
17
	"os"
18
	"sort"
19

20
	"golang.org/x/tools/cover"
21
)
22

23
func mergeProfiles(p, merge *cover.Profile) {
24
	if p.Mode != merge.Mode {
25
		log.Fatalf("cannot merge profiles with different modes")
26
	}
27
	// Since the blocks are sorted, we can keep track of where the last block
28
	// was inserted and only look at the blocks after that as targets for merge
29
	startIndex := 0
30
	for _, b := range merge.Blocks {
31
		startIndex = mergeProfileBlock(p, b, startIndex)
32
	}
33
}
34

35
func mergeProfileBlock(p *cover.Profile, pb cover.ProfileBlock, startIndex int) int {
36
	sortFunc := func(i int) bool {
37
		pi := p.Blocks[i+startIndex]
38
		return pi.StartLine >= pb.StartLine && (pi.StartLine != pb.StartLine || pi.StartCol >= pb.StartCol)
39
	}
40

41
	i := 0
42
	if sortFunc(i) != true {
43
		i = sort.Search(len(p.Blocks)-startIndex, sortFunc)
44
	}
45
	i += startIndex
46
	if i < len(p.Blocks) && p.Blocks[i].StartLine == pb.StartLine && p.Blocks[i].StartCol == pb.StartCol {
47
		if p.Blocks[i].EndLine != pb.EndLine || p.Blocks[i].EndCol != pb.EndCol {
48
			log.Fatalf("OVERLAP MERGE: %v %v %v", p.FileName, p.Blocks[i], pb)
49
		}
50
		switch p.Mode {
51
		case "set":
52
			p.Blocks[i].Count |= pb.Count
53
		case "count", "atomic":
54
			p.Blocks[i].Count += pb.Count
55
		default:
56
			log.Fatalf("unsupported covermode: '%s'", p.Mode)
57
		}
58
	} else {
59
		if i > 0 {
60
			pa := p.Blocks[i-1]
61
			if pa.EndLine >= pb.EndLine && (pa.EndLine != pb.EndLine || pa.EndCol > pb.EndCol) {
62
				log.Fatalf("OVERLAP BEFORE: %v %v %v", p.FileName, pa, pb)
63
			}
64
		}
65
		if i < len(p.Blocks)-1 {
66
			pa := p.Blocks[i+1]
67
			if pa.StartLine <= pb.StartLine && (pa.StartLine != pb.StartLine || pa.StartCol < pb.StartCol) {
68
				log.Fatalf("OVERLAP AFTER: %v %v %v", p.FileName, pa, pb)
69
			}
70
		}
71
		p.Blocks = append(p.Blocks, cover.ProfileBlock{})
72
		copy(p.Blocks[i+1:], p.Blocks[i:])
73
		p.Blocks[i] = pb
74
	}
75
	return i + 1
76
}
77

78
func addProfile(profiles []*cover.Profile, p *cover.Profile) []*cover.Profile {
79
	i := sort.Search(len(profiles), func(i int) bool { return profiles[i].FileName >= p.FileName })
80
	if i < len(profiles) && profiles[i].FileName == p.FileName {
81
		mergeProfiles(profiles[i], p)
82
	} else {
83
		profiles = append(profiles, nil)
84
		copy(profiles[i+1:], profiles[i:])
85
		profiles[i] = p
86
	}
87
	return profiles
88
}
89

90
func dumpProfiles(profiles []*cover.Profile, out io.Writer) {
91
	if len(profiles) == 0 {
92
		return
93
	}
94
	fmt.Fprintf(out, "mode: %s\n", profiles[0].Mode)
95
	for _, p := range profiles {
96
		for _, b := range p.Blocks {
97
			fmt.Fprintf(out, "%s:%d.%d,%d.%d %d %d\n", p.FileName, b.StartLine, b.StartCol, b.EndLine, b.EndCol, b.NumStmt, b.Count)
98
		}
99
	}
100
}
101

102
func main() {
103
	flag.Parse()
104

105
	var merged []*cover.Profile
106

107
	for _, file := range flag.Args() {
108
		profiles, err := cover.ParseProfiles(file)
109
		if err != nil {
110
			log.Fatalf("failed to parse profile '%s': %v", file, err)
111
		}
112
		for _, p := range profiles {
113
			merged = addProfile(merged, p)
114
		}
115
	}
116

117
	dumpProfiles(merged, os.Stdout)
118
}
119

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.