forked from kubevirt/kubevirt
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjunit-merger.go
149 lines (130 loc) · 3.83 KB
/
junit-merger.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package main
import (
"encoding/xml"
"fmt"
"io"
"os"
"path/filepath"
"github.com/onsi/ginkgo/reporters"
flag "github.com/spf13/pflag"
"kubevirt.io/client-go/log"
)
func main() {
if path := os.Getenv("BUILD_WORKSPACE_DIRECTORY"); path != "" {
if err := os.Chdir(path); err != nil {
panic(err)
}
}
var output string
flag.StringVarP(&output, "output", "o", "-", "File to write the resulting junit file to, defaults to stdout (-)")
flag.Parse()
junitFiles := flag.Args()
if len(junitFiles) == 0 {
log.DefaultLogger().Critical("No JUnit files to merge provided.")
}
suites, err := loadJUnitFiles(junitFiles)
if err != nil {
log.DefaultLogger().Reason(err).Critical("Could not load JUnit files.")
}
result, err := mergeJUnitFiles(suites)
if err != nil {
log.DefaultLogger().Reason(err).Critical("Could not merge JUnit files")
}
writer, err := prepareOutput(output)
if err != nil {
log.DefaultLogger().Reason(err).Critical("Failed to prepare the output file")
}
err = writeJunitFile(writer, result)
if err != nil {
log.DefaultLogger().Reason(err).Critical("Failed to write the merged junit report")
}
}
func loadJUnitFiles(fileGlobs []string) (suites []reporters.JUnitTestSuite, err error) {
for _, fileglob := range fileGlobs {
files, err := filepath.Glob(fileglob)
if err != nil {
return nil, err
}
for _, file := range files {
f, err := os.Open(file)
if err != nil {
return nil, fmt.Errorf("failed to open file %s: %v", file, err)
}
suite := reporters.JUnitTestSuite{}
err = xml.NewDecoder(f).Decode(&suite)
if err != nil {
return nil, fmt.Errorf("failed to decode suite %s: %v", file, err)
}
suites = append(suites, suite)
}
}
return suites, nil
}
func mergeJUnitFiles(suites []reporters.JUnitTestSuite) (result *reporters.JUnitTestSuite, err error) {
result = &reporters.JUnitTestSuite{}
ran := map[string]reporters.JUnitTestCase{}
skipped := map[string]reporters.JUnitTestCase{}
skippedList := []string{}
// If tests ran in any of the suites, ensure it ends up in the ran-map and not in the skipped map.
// If it only ever got skipped, keep it in the skip map
for _, suite := range suites {
for _, testcase := range suite.TestCases {
if testcase.Skipped == nil {
if _, exists := skipped[testcase.Name]; exists {
delete(skipped, testcase.Name)
}
if _, exists := ran[testcase.Name]; exists {
return nil, fmt.Errorf("test '%s' was executed multiple times", testcase.Name)
}
ran[testcase.Name] = testcase
result.TestCases = append(result.TestCases, testcase)
} else if testcase.Skipped != nil {
if _, exists := ran[testcase.Name]; !exists {
if _, exists := skipped[testcase.Name]; exists {
testcase.Time = skipped[testcase.Name].Time + testcase.Time
} else {
skippedList = append(skippedList, testcase.Name)
}
skipped[testcase.Name] = testcase
}
}
}
}
result.Name = "Merged Test Suite"
for _, suite := range suites {
result.Time += suite.Time
result.Tests += suite.Tests
result.Failures += suite.Failures
result.Errors += suite.Errors
}
for _, casename := range skippedList {
if _, exists := ran[casename]; exists {
continue
}
if _, exists := skipped[casename]; !exists {
panic("can't happen if we don't have a bug")
}
result.TestCases = append(result.TestCases, skipped[casename])
}
result.TestCases = append(result.TestCases)
return result, nil
}
func prepareOutput(output string) (writer io.Writer, err error) {
writer = os.Stdout
if output != "-" && output != "" {
writer, err = os.Create(output)
if err != nil {
return nil, err
}
}
return writer, nil
}
func writeJunitFile(writer io.Writer, suite *reporters.JUnitTestSuite) error {
encoder := xml.NewEncoder(writer)
encoder.Indent("", " ")
err := encoder.Encode(suite)
if err != nil {
return err
}
return nil
}