@@ -17,6 +17,7 @@ package output
17
17
import (
18
18
"encoding/csv"
19
19
"encoding/json"
20
+ "encoding/xml"
20
21
htmlTemplate "html/template"
21
22
"io"
22
23
plainTemplate "text/template"
@@ -36,6 +37,9 @@ const (
36
37
37
38
// ReportCSV set the output format to csv
38
39
ReportCSV // CSV format
40
+
41
+ // ReportXML set the output format to junit xml
42
+ ReportXML // JUnit XML format
39
43
)
40
44
41
45
var text = `Results:
@@ -57,6 +61,30 @@ type reportInfo struct {
57
61
Stats * gas.Metrics
58
62
}
59
63
64
+ type XMLReport struct {
65
+ XMLName xml.Name `xml:"testsuites"`
66
+ Testsuites []Testsuite `xml:"testsuite"`
67
+ }
68
+
69
+ type Testsuite struct {
70
+ XMLName xml.Name `xml:"testsuite"`
71
+ Name string `xml:"name,attr"`
72
+ Tests int `xml:"tests,attr"`
73
+ Testcases []Testcase `xml:"testcase"`
74
+ }
75
+
76
+ type Testcase struct {
77
+ XMLName xml.Name `xml:"testcase"`
78
+ Name string `xml:"name,attr"`
79
+ Failure Failure `xml:"failure"`
80
+ }
81
+
82
+ type Failure struct {
83
+ XMLName xml.Name `xml:"failure"`
84
+ Message string `xml:"message,attr"`
85
+ Text string `xml:",innerxml"`
86
+ }
87
+
60
88
// CreateReport generates a report based for the supplied issues and metrics given
61
89
// the specified format. The formats currently accepted are: json, csv, html and text.
62
90
func CreateReport (w io.Writer , format string , issues []* gas.Issue , metrics * gas.Metrics ) error {
@@ -70,6 +98,8 @@ func CreateReport(w io.Writer, format string, issues []*gas.Issue, metrics *gas.
70
98
err = reportJSON (w , data )
71
99
case "csv" :
72
100
err = reportCSV (w , data )
101
+ case "xml" :
102
+ err = reportXML (w , data )
73
103
case "html" :
74
104
err = reportFromHTMLTemplate (w , html , data )
75
105
case "text" :
@@ -112,6 +142,52 @@ func reportCSV(w io.Writer, data *reportInfo) error {
112
142
return nil
113
143
}
114
144
145
+ func reportXML (w io.Writer , data * reportInfo ) error {
146
+ testsuites := make (map [string ][]Testcase )
147
+ for _ , issue := range data .Issues {
148
+ stacktrace , err := json .MarshalIndent (issue , "" , "\t " )
149
+ if err != nil {
150
+ panic (err )
151
+ }
152
+ testcase := Testcase {
153
+ Name : issue .File ,
154
+ Failure : Failure {
155
+ Message : "Found 1 vulnerability. See stacktrace for details." ,
156
+ Text : string (stacktrace ),
157
+ },
158
+ }
159
+ if _ , ok := testsuites [issue .What ]; ok {
160
+ testsuites [issue .What ] = append (testsuites [issue .What ], testcase )
161
+ } else {
162
+ testsuites [issue .What ] = []Testcase {testcase }
163
+ }
164
+ }
165
+
166
+ var xmlReport XMLReport
167
+ for what , testcases := range testsuites {
168
+ testsuite := Testsuite {
169
+ Name : what ,
170
+ Tests : len (testcases ),
171
+ }
172
+ for _ , testcase := range testcases {
173
+ testsuite .Testcases = append (testsuite .Testcases , testcase )
174
+ }
175
+ xmlReport .Testsuites = append (xmlReport .Testsuites , testsuite )
176
+ }
177
+
178
+ raw , err := xml .Marshal (xmlReport )
179
+ if err != nil {
180
+ panic (err )
181
+ }
182
+
183
+ _ , err = w .Write (raw )
184
+ if err != nil {
185
+ panic (err )
186
+ }
187
+
188
+ return err
189
+ }
190
+
115
191
func reportFromPlaintextTemplate (w io.Writer , reportTemplate string , data * reportInfo ) error {
116
192
t , e := plainTemplate .New ("gas" ).Parse (reportTemplate )
117
193
if e != nil {
0 commit comments