Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix golang test ingestion #33

Merged
merged 2 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/junit2jira/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ func run(p params) error {
jiraClient: jiraClient,
}

testSuites, err := junit.IngestDir(p.junitReportsDir)
testSuites, err := testcase.LoadTestSuites(p.junitReportsDir)
if err != nil {
log.Fatalf("could not read files: %s", err)
}
Expand Down
55 changes: 36 additions & 19 deletions cmd/junit2jira/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,26 @@ package main
import (
"bytes"
_ "embed"
"github.com/stackrox/junit2jira/pkg/testcase"
"net/url"
"testing"

"github.com/andygrunwald/go-jira"
"github.com/joshdk/go-junit"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestParseJunitReport(t *testing.T) {
t.Run("not existing", func(t *testing.T) {
tests, err := junit.IngestDir("not existing")
tests, err := testcase.LoadTestSuites("not existing")
assert.Error(t, err)
assert.Nil(t, tests)
})
t.Run("golang", func(t *testing.T) {
j := junit2jira{
params: params{junitReportsDir: "testdata/jira/report.xml"},
}
testsSuites, err := junit.IngestDir(j.junitReportsDir)
testsSuites, err := testcase.LoadTestSuites(j.junitReportsDir)
assert.NoError(t, err)
tests, err := j.getMergedFailedTests(testsSuites)
assert.NoError(t, err)
Expand All @@ -47,7 +47,7 @@ func TestParseJunitReport(t *testing.T) {
j := junit2jira{
params: params{junitReportsDir: "testdata/jira/report.xml", JobName: "job-name", threshold: 1},
}
testsSuites, err := junit.IngestDir(j.junitReportsDir)
testsSuites, err := testcase.LoadTestSuites(j.junitReportsDir)
assert.NoError(t, err)
tests, err := j.getMergedFailedTests(testsSuites)
assert.NoError(t, err)
Expand All @@ -65,7 +65,7 @@ github.com/stackrox/rox/sensor/kubernetes/localscanner / TestLocalScannerTLSIssu
j := junit2jira{
params: params{junitReportsDir: "testdata/jira", JobName: "job-name", BuildId: "1", threshold: 3},
}
testsSuites, err := junit.IngestDir(j.junitReportsDir)
testsSuites, err := testcase.LoadTestSuites(j.junitReportsDir)
assert.NoError(t, err)
tests, err := j.getMergedFailedTests(testsSuites)
assert.NoError(t, err)
Expand All @@ -75,6 +75,7 @@ github.com/stackrox/rox/sensor/kubernetes/localscanner / TestLocalScannerTLSIssu
[]j2jTestCase{
{
Message: `DefaultPoliciesTest / Verify policy Apache Struts CVE-2017-5638 is triggered FAILED
github.com/stackrox/rox/pkg/grpc / Test_APIServerSuite/Test_TwoTestsStartingAPIs FAILED
central-basic / step 90-activate-scanner-v4 FAILED
github.com/stackrox/rox/pkg/booleanpolicy/evaluator / TestDifferentBaseTypes FAILED
github.com/stackrox/rox/sensor/kubernetes/localscanner / TestLocalScannerTLSIssuerIntegrationTests FAILED
Expand All @@ -93,7 +94,7 @@ command-line-arguments / TestTimeout FAILED
j := junit2jira{
params: params{junitReportsDir: "testdata/jira", BuildId: "1"},
}
testsSuites, err := junit.IngestDir(j.junitReportsDir)
testsSuites, err := testcase.LoadTestSuites(j.junitReportsDir)
assert.NoError(t, err)
tests, err := j.getMergedFailedTests(testsSuites)
assert.NoError(t, err)
Expand Down Expand Up @@ -135,6 +136,20 @@ command-line-arguments / TestTimeout FAILED
"\n" +
"\tat DefaultPoliciesTest.Verify policy #policyName is triggered(DefaultPoliciesTest.groovy:181)\n",
},
{
Name: "Test_APIServerSuite/Test_TwoTestsStartingAPIs",
Message: "No test result found",
Stdout: "",
Suite: "github.com/stackrox/rox/pkg/grpc",
BuildId: "1",
Error: ` testutils.go:94: Stopping [2] listeners
testutils.go:87: [http handler listener: stopped]
testutils.go:87: [gRPC server listener: not stopped in loop. Comparing with grpcServer pointer with listener.srv pointer (0xc002ab2e00 : 0xc002ab2e00)]
server_test.go:229: -----------------------------------------------
server_test.go:230: STACK TRACE INFO
server_test.go:231: -----------------------------------------------
`,
},
{
Name: "TestDifferentBaseTypes",
Suite: "github.com/stackrox/rox/pkg/booleanpolicy/evaluator",
Expand Down Expand Up @@ -176,9 +191,9 @@ command-line-arguments / TestTimeout FAILED
})
t.Run("gradle", func(t *testing.T) {
j := junit2jira{
params: params{junitReportsDir: "testdata/jira/TEST-DefaultPoliciesTest.xml", BuildId: "1"},
params: params{junitReportsDir: "testdata/jira/csv/TEST-DefaultPoliciesTest.xml", BuildId: "1"},
}
testsSuites, err := junit.IngestDir(j.junitReportsDir)
testsSuites, err := testcase.LoadTestSuites(j.junitReportsDir)
assert.NoError(t, err)
tests, err := j.getMergedFailedTests(testsSuites)
assert.NoError(t, err)
Expand Down Expand Up @@ -304,19 +319,17 @@ waitForViolation(deploymentName, policyName, 60)

func TestCsvOutput(t *testing.T) {
p := params{
BuildId: "1",
JobName: "comma ,",
Orchestrator: "test",
BuildTag: "0.0.0",
BaseLink: `quote "`,
BuildLink: "buildLink",
timestamp: "time",
BuildId: "1",
JobName: "comma ,",
Orchestrator: "test",
BuildTag: "0.0.0",
BaseLink: `quote "`,
BuildLink: "buildLink",
timestamp: "time",
junitReportsDir: "testdata/jira/csv",
}
buf := bytes.NewBufferString("")
testSuites, err := junit.IngestFiles([]string{
"testdata/jira/TEST-DefaultPoliciesTest.xml",
"testdata/jira/kuttl-report.xml",
})
testSuites, err := testcase.LoadTestSuites(p.junitReportsDir)
assert.NoError(t, err)
err = junit2csv(testSuites, p, buf)
assert.NoError(t, err)
Expand All @@ -337,6 +350,10 @@ func TestCsvOutput(t *testing.T) {
1,time,DefaultPoliciesTest,Verify that built-in services don't trigger unexpected alerts,0,skipped,"comma ,",0.0.0
1,time,DefaultPoliciesTest,Verify that alert counts API is consistent with alerts,0,skipped,"comma ,",0.0.0
1,time,DefaultPoliciesTest,Verify that alert groups API is consistent with alerts,0,skipped,"comma ,",0.0.0
1,time,github.com/stackrox/rox/pkg/grpc,Test_APIServerSuite/Test_TwoTestsStartingAPIs,0,error,"comma ,",0.0.0
1,time,github.com/stackrox/rox/pkg/grpc/authz/user,TestLogInternalErrorInterceptor,0,passed,"comma ,",0.0.0
1,time,fallback-classname,TestNoClassname,0,passed,"comma ,",0.0.0
1,time,TestNoName,fallback-name,0,passed,"comma ,",0.0.0
1,time,central-basic,setup,0,passed,"comma ,",0.0.0
1,time,central-basic,step 0-image-pull-secrets,0,passed,"comma ,",0.0.0
1,time,central-basic,step 10-central-cr,0,passed,"comma ,",0.0.0
Expand Down
17 changes: 17 additions & 0 deletions cmd/junit2jira/testdata/jira/csv/golang-junit-report1.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuites tests="2" errors="1">
<testsuite name="github.com/stackrox/rox/pkg/grpc" tests="1" failures="0" errors="1" id="0" hostname="test" time="28.018" timestamp="2024-12-05T18:53:27+01:00">
<testcase name="Test_APIServerSuite/Test_TwoTestsStartingAPIs" classname="github.com/stackrox/rox/pkg/grpc" time="0.000">
<error message="No test result found"><![CDATA[ testutils.go:94: Stopping [2] listeners
testutils.go:87: [http handler listener: stopped]
testutils.go:87: [gRPC server listener: not stopped in loop. Comparing with grpcServer pointer with listener.srv pointer (0xc002ab2e00 : 0xc002ab2e00)]
server_test.go:229: -----------------------------------------------
server_test.go:230: STACK TRACE INFO
server_test.go:231: -----------------------------------------------
]]></error>
</testcase>
</testsuite>
<testsuite name="" tests="1" failures="0" errors="0" id="1" hostname="test" time="0.000" timestamp="2024-12-05T18:53:27+01:00">
<testcase name="TestLogInternalErrorInterceptor" classname="github.com/stackrox/rox/pkg/grpc/authz/user" time="0.000"></testcase>
</testsuite>
</testsuites>
19 changes: 19 additions & 0 deletions cmd/junit2jira/testdata/jira/csv/golang-junit-report2-bad.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuites tests="3" errors="3">
<testsuite name="runtime.MemStats" tests="1" failures="0" errors="1" id="0" hostname="test" time="0.000" timestamp="2024-12-05T18:53:27+01:00">
<testcase name="" classname="runtime.MemStats" time="0.000">
<error message="Build error"><![CDATA[# Alloc = 63549840
# TotalAlloc = 140555368
# Sys = 91578648
# Lookups = 0
# Mallocs = 970690
# Frees = 649401]]></error>
</testcase>
</testsuite>
<testsuite name="" tests="1" failures="0" errors="1" id="1" hostname="test" time="0.000" timestamp="2024-12-05T18:53:27+01:00">
<testcase name="TestNoClassname" classname="" time="0.000"></testcase>
</testsuite>
<testsuite name="" tests="1" failures="0" errors="1" id="2" hostname="test" time="0.000" timestamp="2024-12-05T18:53:27+01:00">
<testcase name="" classname="TestNoName" time="0.000"></testcase>
</testsuite>
</testsuites>
63 changes: 63 additions & 0 deletions pkg/testcase/testcase.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ package testcase
import (
"fmt"
"github.com/joshdk/go-junit"
"slices"
"strings"
)

const subTestFormat = "\nSub test %s: %s"
const fallbackName = "fallback-name"
const fallbackClassname = "fallback-classname"

type TestCase struct {
Name string
Expand All @@ -19,6 +22,66 @@ type TestCase struct {
IsSubtest bool
}

type ignoreTestCase struct {
Name string
Classname string
}

var ignoreList = []ignoreTestCase{
{Name: "", Classname: "runtime.MemStats"},
mtodor marked this conversation as resolved.
Show resolved Hide resolved
}

// LoadTestSuites loads all reports in provided directory.
mtodor marked this conversation as resolved.
Show resolved Hide resolved
func LoadTestSuites(reportDir string) ([]junit.Suite, error) {
testSuites, err := junit.IngestDir(reportDir)
if err != nil {
return nil, err
}

return getClearedSuites(testSuites), nil
}

func deleteHelperTest(testElem junit.Test) bool {
for _, ignore := range ignoreList {
if testElem.Name == ignore.Name && testElem.Classname == ignore.Classname {
return true
}
}

return false
}

func addFallbacks(tests []junit.Test) []junit.Test {
mtodor marked this conversation as resolved.
Show resolved Hide resolved
for i, _ := range tests {
if tests[i].Classname == "" {
tests[i].Classname = fallbackClassname
}

if tests[i].Name == "" {
tests[i].Name = fallbackName
}
}

return tests
}

// getClearedSuites recursively removes ignored tests.
func getClearedSuites(suites []junit.Suite) []junit.Suite {
resSuites := make([]junit.Suite, 0, len(suites))
for _, suite := range suites {
suite.Suites = getClearedSuites(suite.Suites)
suite.Tests = addFallbacks(slices.DeleteFunc(suite.Tests, deleteHelperTest))

// Filter out empty suites.
if len(suite.Suites) == 0 && len(suite.Tests) == 0 {
continue
}
resSuites = append(resSuites, suite)
}

return resSuites
}

func (tc *TestCase) addSubTest(subTest junit.Test) {
if subTest.Message != "" {
tc.Message += fmt.Sprintf(subTestFormat, subTest.Name, subTest.Message)
Expand Down
Loading
Loading