2024-11-20 20:13:17 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/xml"
|
2024-11-20 22:35:05 +00:00
|
|
|
"strings"
|
2024-11-20 20:13:17 +00:00
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Testsuites struct {
|
2024-11-20 21:15:44 +00:00
|
|
|
XMLName xml.Name `xml:"testsuites"`
|
2024-11-20 20:13:17 +00:00
|
|
|
|
|
|
|
Tests int `xml:"tests,attr"`
|
|
|
|
Failures int `xml:"failures,attr"`
|
|
|
|
Errors int `xml:"errors,attr"`
|
|
|
|
Disabled int `xml:"disabled,attr,omitempty"`
|
|
|
|
Skipped int `xml:"skipped,attr,omitempty"`
|
|
|
|
|
|
|
|
Time float64 `xml:"time,attr"`
|
|
|
|
|
2024-11-22 19:59:23 +00:00
|
|
|
Suites []*Test `xml:"testsuite,omitempty"`
|
2024-11-20 20:13:17 +00:00
|
|
|
}
|
|
|
|
|
2024-11-22 19:59:23 +00:00
|
|
|
type Test struct {
|
2024-11-20 21:32:49 +00:00
|
|
|
XMLName xml.Name `xml:"testsuite"`
|
|
|
|
|
2024-11-20 20:13:17 +00:00
|
|
|
// required attributes
|
2024-11-22 19:59:23 +00:00
|
|
|
Name string `xml:"name,attr"`
|
|
|
|
TestCount int `xml:"tests,attr"`
|
|
|
|
Failures int `xml:"failures,attr"`
|
|
|
|
Errors int `xml:"errors,attr"`
|
2024-11-20 20:13:17 +00:00
|
|
|
|
|
|
|
// optional attributes
|
|
|
|
Disabled int `xml:"disabled,attr,omitempty"`
|
|
|
|
Package string `xml:"package,attr,omitempty"`
|
|
|
|
Skipped int `xml:"skipped,attr,omitempty"`
|
2024-11-22 19:59:23 +00:00
|
|
|
Time float64 `xml:"time,attr"`
|
2024-11-20 20:13:17 +00:00
|
|
|
Timestamp time.Time `xml:"timestamp,attr,omitempty"`
|
|
|
|
|
2024-11-22 19:59:23 +00:00
|
|
|
Tests []*Test `xml:"testsuite,omitempty"`
|
|
|
|
SystemOut string `xml:"system-out,omitempty"`
|
|
|
|
|
2024-12-13 21:24:18 +00:00
|
|
|
hasTests bool
|
|
|
|
parent *Test
|
|
|
|
t0 time.Time
|
2024-11-20 20:13:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type Result struct {
|
|
|
|
Message string `xml:"message,attr"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type Testcase struct {
|
|
|
|
// required attributes
|
|
|
|
Name string `xml:"name,attr"`
|
|
|
|
Classname string `xml:"classname,attr"`
|
|
|
|
|
|
|
|
// optional attributes
|
|
|
|
Time float64 `xml:"time,attr,omitempty"`
|
|
|
|
|
|
|
|
Skipped *Result `xml:"skipped,omitempty"`
|
|
|
|
Error *Result `xml:"error,omitempty"`
|
|
|
|
Failure *Result `xml:"failure,omitempty"`
|
|
|
|
SystemOut string `xml:"system-out,omitempty"`
|
|
|
|
}
|
|
|
|
|
2024-11-22 19:59:23 +00:00
|
|
|
// Looks for a test in root
|
|
|
|
func (testsuites *Testsuites) getRootSuite(t time.Time, pkg string, create bool) *Test {
|
2024-11-20 20:13:17 +00:00
|
|
|
for _, suite := range testsuites.Suites {
|
|
|
|
if suite.Name == pkg {
|
|
|
|
return suite
|
|
|
|
}
|
|
|
|
}
|
2024-11-22 19:59:23 +00:00
|
|
|
if !create {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
suite := Test{
|
2024-11-20 20:13:17 +00:00
|
|
|
Name: pkg,
|
|
|
|
Skipped: 0,
|
|
|
|
Timestamp: t,
|
2024-11-22 21:42:02 +00:00
|
|
|
t0: t,
|
2024-11-20 20:13:17 +00:00
|
|
|
}
|
|
|
|
testsuites.Suites = append(testsuites.Suites, &suite)
|
|
|
|
return &suite
|
|
|
|
}
|
|
|
|
|
2024-11-22 19:59:23 +00:00
|
|
|
func (suite *Test) getSuite(t time.Time, name string) *Test {
|
|
|
|
for _, s := range suite.Tests {
|
2024-11-20 22:42:06 +00:00
|
|
|
if s.Name == suite.Name+"/"+name {
|
2024-11-20 20:13:17 +00:00
|
|
|
return s
|
|
|
|
}
|
|
|
|
}
|
2024-11-22 19:59:23 +00:00
|
|
|
s := Test{
|
2024-11-20 22:35:05 +00:00
|
|
|
Name: suite.Name + "/" + name,
|
2024-11-20 20:13:17 +00:00
|
|
|
Timestamp: t,
|
2024-11-22 21:42:02 +00:00
|
|
|
t0: t,
|
2024-11-20 20:13:17 +00:00
|
|
|
}
|
2024-11-22 19:59:23 +00:00
|
|
|
suite.Tests = append(suite.Tests, &s)
|
2024-11-20 20:13:17 +00:00
|
|
|
return &s
|
|
|
|
}
|
|
|
|
|
2024-11-22 19:59:23 +00:00
|
|
|
func (suite *Test) getTest(t time.Time, testname string) *Test {
|
2024-11-22 21:42:02 +00:00
|
|
|
if testname == "" {
|
|
|
|
return suite
|
|
|
|
}
|
2024-11-20 22:35:05 +00:00
|
|
|
suitename := suite.Name
|
|
|
|
path := strings.Split(testname, "/")
|
2024-11-22 19:59:23 +00:00
|
|
|
for i := 0; i < len(path); i++ {
|
2024-11-20 22:35:05 +00:00
|
|
|
suite = suite.getSuite(t, path[i])
|
|
|
|
suitename = suitename + "/" + path[i]
|
|
|
|
}
|
2024-11-22 19:59:23 +00:00
|
|
|
return suite
|
2024-11-20 20:13:17 +00:00
|
|
|
}
|
|
|
|
|
2024-11-22 19:59:23 +00:00
|
|
|
func (testsuites *Testsuites) getTest(t time.Time, pkg string, testname string) *Test {
|
|
|
|
suite := testsuites.getRootSuite(t, pkg, true)
|
2024-11-20 20:13:17 +00:00
|
|
|
test := suite.getTest(t, testname)
|
|
|
|
return test
|
|
|
|
}
|
|
|
|
|
2024-11-22 21:42:02 +00:00
|
|
|
func (testsuites *Testsuites) Start(t time.Time, pkg string) {
|
2024-11-22 19:59:23 +00:00
|
|
|
testsuites.getRootSuite(t, pkg, true)
|
2024-11-20 20:13:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (testsuites *Testsuites) Test(t time.Time, pkg string, test string) {
|
2024-11-22 19:59:23 +00:00
|
|
|
// This can be a test suite as well
|
2024-12-13 21:24:18 +00:00
|
|
|
testobj := testsuites.getTest(t, pkg, test)
|
|
|
|
testobj.hasTests = true
|
2024-11-20 20:13:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (testsuites *Testsuites) Output(t time.Time, pkg string, test string, output string) {
|
|
|
|
tc := testsuites.getTest(t, pkg, test)
|
|
|
|
tc.SystemOut = tc.SystemOut + output
|
|
|
|
}
|
|
|
|
|
2024-11-22 21:42:02 +00:00
|
|
|
func (testsuites *Testsuites) Pass(t time.Time, pkg string, test string) {
|
2024-11-22 21:03:23 +00:00
|
|
|
tc := testsuites.getTest(t, pkg, test)
|
2024-11-22 21:42:02 +00:00
|
|
|
tc.Time = float64(t.Sub(tc.t0).Nanoseconds()) / 1000_000_000.0
|
2024-11-20 20:13:17 +00:00
|
|
|
}
|
|
|
|
|
2024-11-22 21:42:02 +00:00
|
|
|
func (testsuites *Testsuites) Bench(t time.Time, pkg string, test string, output string) {
|
2024-11-20 20:13:17 +00:00
|
|
|
tc := testsuites.getTest(t, pkg, test)
|
|
|
|
tc.SystemOut = tc.SystemOut + output + "\n"
|
|
|
|
}
|
|
|
|
|
2024-11-22 21:42:02 +00:00
|
|
|
func (testsuites *Testsuites) Fail(t time.Time, pkg string, test string) {
|
2024-11-20 20:13:17 +00:00
|
|
|
tc := testsuites.getTest(t, pkg, test)
|
2024-11-22 21:42:02 +00:00
|
|
|
tc.Time = float64(t.Sub(tc.t0).Nanoseconds()) / 1000_000_000.0
|
2024-11-22 19:59:23 +00:00
|
|
|
tc.Failures = 1
|
2024-11-20 20:13:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (testsuites *Testsuites) Skip(t time.Time, pkg string, test string) {
|
2024-11-22 19:59:23 +00:00
|
|
|
tc := testsuites.getTest(t, pkg, test)
|
2024-11-22 21:42:02 +00:00
|
|
|
tc.Time = float64(t.Sub(tc.t0).Nanoseconds()) / 1000_000_000.0
|
2024-11-22 19:59:23 +00:00
|
|
|
tc.Skipped = 1
|
2024-11-20 20:13:17 +00:00
|
|
|
}
|
|
|
|
|
2024-11-22 19:59:23 +00:00
|
|
|
func (suite *Test) Complete() {
|
|
|
|
suite.TestCount = 0
|
2024-12-13 21:24:18 +00:00
|
|
|
if len(suite.Tests) > 0 {
|
|
|
|
suite.Failures = 0
|
|
|
|
suite.Errors = 0
|
|
|
|
suite.Disabled = 0
|
|
|
|
suite.Skipped = 0
|
|
|
|
}
|
2024-11-22 19:59:23 +00:00
|
|
|
|
2024-12-13 21:24:18 +00:00
|
|
|
if len(suite.Tests) == 0 && suite.hasTests {
|
2024-11-22 19:59:23 +00:00
|
|
|
suite.TestCount = 1
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, ts := range suite.Tests {
|
2024-11-20 20:13:17 +00:00
|
|
|
ts.Complete()
|
2024-11-22 19:59:23 +00:00
|
|
|
suite.TestCount += ts.TestCount
|
2024-11-20 20:13:17 +00:00
|
|
|
suite.Failures += ts.Failures
|
|
|
|
suite.Errors += ts.Errors
|
|
|
|
suite.Disabled += ts.Disabled
|
|
|
|
suite.Skipped += ts.Skipped
|
2024-11-22 21:42:02 +00:00
|
|
|
ts.parent = suite
|
2024-11-20 20:13:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (testsuites *Testsuites) Complete() {
|
|
|
|
testsuites.Tests = 0
|
|
|
|
testsuites.Failures = 0
|
|
|
|
testsuites.Errors = 0
|
|
|
|
testsuites.Disabled = 0
|
|
|
|
testsuites.Skipped = 0
|
|
|
|
for _, ts := range testsuites.Suites {
|
|
|
|
ts.Complete()
|
2024-11-22 19:59:23 +00:00
|
|
|
testsuites.Tests += ts.TestCount
|
2024-11-20 20:13:17 +00:00
|
|
|
testsuites.Failures += ts.Failures
|
|
|
|
testsuites.Errors += ts.Errors
|
|
|
|
testsuites.Disabled += ts.Disabled
|
|
|
|
testsuites.Skipped += ts.Skipped
|
|
|
|
}
|
|
|
|
}
|