//go:build unit
// +build unit
package cmd
import (
"bytes"
"encoding/xml"
"errors"
"fmt"
"os"
"testing"
"github.com/SAP/jenkins-library/pkg/abaputils"
"github.com/SAP/jenkins-library/pkg/mock"
"github.com/stretchr/testify/assert"
)
func TestBuildAUnitRequestBody(t *testing.T) {
t.Parallel()
t.Run("Test AUnit test run body with no data", func(t *testing.T) {
t.Parallel()
var config abapEnvironmentRunAUnitTestOptions
bodyString, err := buildAUnitRequestBody(config)
expectedBodyString := ""
assert.Equal(t, expectedBodyString, bodyString)
assert.EqualError(t, err, "No configuration provided - please provide either an AUnit configuration file or a repository configuration file")
})
t.Run("Test AUnit test run body with example yaml config of not supported Object Sets", func(t *testing.T) {
t.Parallel()
expectedoptionsString := ``
expectedobjectSetString := ``
config := AUnitConfig{
Title: "Test Title",
Context: "Test Context",
Options: AUnitOptions{
Measurements: "none",
Scope: Scope{
OwnTests: new(bool),
ForeignTests: new(bool),
},
RiskLevel: RiskLevel{
Harmless: new(bool),
Dangerous: new(bool),
Critical: new(bool),
},
Duration: Duration{
Short: new(bool),
Medium: new(bool),
Long: new(bool),
},
},
ObjectSet: abaputils.ObjectSet{
Type: "testSet",
Set: []abaputils.Set{
{
Type: "testSet",
Set: []abaputils.Set{
{
Type: "testAUnitFlatObjectSet",
FlatObjectSet: []abaputils.FlatObjectSet{
{
Name: "TestCLAS",
Type: "CLAS",
},
{
Name: "TestINTF",
Type: "INTF",
},
},
},
{
Type: "testAUnitObjectTypeSet",
ObjectTypeSet: []abaputils.ObjectTypeSet{
{
Name: "TestObjectType",
},
},
},
},
},
},
},
}
objectSetString := abaputils.BuildOSLString(config.ObjectSet)
optionsString := buildAUnitOptionsString(config)
assert.Equal(t, expectedoptionsString, optionsString)
assert.Equal(t, expectedobjectSetString, objectSetString)
})
t.Run("Test AUnit test run body with example yaml config of only Multi Property Set", func(t *testing.T) {
t.Parallel()
expectedoptionsString := ``
expectedobjectSetString := ``
config := AUnitConfig{
Title: "Test Title",
Context: "Test Context",
Options: AUnitOptions{
Measurements: "none",
Scope: Scope{
OwnTests: new(bool),
ForeignTests: new(bool),
},
RiskLevel: RiskLevel{
Harmless: new(bool),
Dangerous: new(bool),
Critical: new(bool),
},
Duration: Duration{
Short: new(bool),
Medium: new(bool),
Long: new(bool),
},
},
ObjectSet: abaputils.ObjectSet{
Type: "multiPropertySet",
MultiPropertySet: abaputils.MultiPropertySet{
SoftwareComponents: []abaputils.SoftwareComponents{
{
Name: "testComponent1",
},
{
Name: "testComponent2",
},
},
},
},
}
objectSetString := abaputils.BuildOSLString(config.ObjectSet)
optionsString := buildAUnitOptionsString(config)
assert.Equal(t, expectedoptionsString, optionsString)
assert.Equal(t, expectedobjectSetString, objectSetString)
})
t.Run("Test AUnit test run body with example yaml config of only Multi Property Set but empty type", func(t *testing.T) {
t.Parallel()
expectedoptionsString := ``
expectedobjectSetString := ``
config := AUnitConfig{
Title: "Test Title",
Context: "Test Context",
Options: AUnitOptions{
Measurements: "none",
Scope: Scope{
OwnTests: new(bool),
ForeignTests: new(bool),
},
RiskLevel: RiskLevel{
Harmless: new(bool),
Dangerous: new(bool),
Critical: new(bool),
},
Duration: Duration{
Short: new(bool),
Medium: new(bool),
Long: new(bool),
},
},
ObjectSet: abaputils.ObjectSet{
Type: "",
MultiPropertySet: abaputils.MultiPropertySet{
SoftwareComponents: []abaputils.SoftwareComponents{
{
Name: "testComponent1",
},
{
Name: "testComponent2",
},
},
},
},
}
objectSetString := abaputils.BuildOSLString(config.ObjectSet)
optionsString := buildAUnitOptionsString(config)
assert.Equal(t, expectedoptionsString, optionsString)
assert.Equal(t, expectedobjectSetString, objectSetString)
})
t.Run("Test AUnit test run body with example yaml config of only Multi Property Set with scomps & packages on top level", func(t *testing.T) {
t.Parallel()
expectedoptionsString := ``
expectedobjectSetString := ``
config := AUnitConfig{
Title: "Test Title",
Context: "Test Context",
Options: AUnitOptions{
Measurements: "none",
Scope: Scope{
OwnTests: new(bool),
ForeignTests: new(bool),
},
RiskLevel: RiskLevel{
Harmless: new(bool),
Dangerous: new(bool),
Critical: new(bool),
},
Duration: Duration{
Short: new(bool),
Medium: new(bool),
Long: new(bool),
},
},
ObjectSet: abaputils.ObjectSet{
PackageNames: []abaputils.Package{{
Name: "testPackage1",
}, {
Name: "testPackage2",
}},
SoftwareComponents: []abaputils.SoftwareComponents{{
Name: "testComponent1",
}, {
Name: "testComponent2",
}},
},
}
objectSetString := abaputils.BuildOSLString(config.ObjectSet)
optionsString := buildAUnitOptionsString(config)
assert.Equal(t, expectedoptionsString, optionsString)
assert.Equal(t, expectedobjectSetString, objectSetString)
})
t.Run("Test AUnit test run body with example yaml config: no Options", func(t *testing.T) {
t.Parallel()
expectedoptionsString := ``
config := AUnitConfig{
Title: "Test", Context: "Test",
ObjectSet: abaputils.ObjectSet{
PackageNames: []abaputils.Package{{
Name: "testPackage1",
}},
SoftwareComponents: []abaputils.SoftwareComponents{{
Name: "testComponent1",
}},
},
}
optionsString := buildAUnitOptionsString(config)
assert.Equal(t, expectedoptionsString, optionsString)
})
t.Run("Config with repository-yml", func(t *testing.T) {
config := abapEnvironmentRunAUnitTestOptions{
AUnitResultsFileName: "aUnitResults.xml",
Repositories: "repositories.yml",
}
dir := t.TempDir()
oldCWD, _ := os.Getwd()
_ = os.Chdir(dir)
// clean up tmp dir
defer func() {
_ = os.Chdir(oldCWD)
}()
repositories := `repositories:
- name: /DMO/REPO
branch: main
`
expectedBodyString := ""
err := os.WriteFile(config.Repositories, []byte(repositories), 0o644)
if assert.Equal(t, err, nil) {
bodyString, err := buildAUnitRequestBody(config)
assert.Equal(t, nil, err)
assert.Equal(t, expectedBodyString, bodyString)
}
})
t.Run("Config with aunitconfig-yml", func(t *testing.T) {
config := abapEnvironmentRunAUnitTestOptions{
AUnitResultsFileName: "aUnitResults.xml",
AUnitConfig: "aunit.yml",
}
dir := t.TempDir()
oldCWD, _ := os.Getwd()
_ = os.Chdir(dir)
// clean up tmp dir
defer func() {
_ = os.Chdir(oldCWD)
}()
yamlBody := `title: My AUnit run
objectset:
packages:
- name: Z_TEST
softwarecomponents:
- name: Z_TEST
- name: /DMO/SWC
`
expectedBodyString := ""
err := os.WriteFile(config.AUnitConfig, []byte(yamlBody), 0o644)
if assert.Equal(t, err, nil) {
bodyString, err := buildAUnitRequestBody(config)
assert.Equal(t, nil, err)
assert.Equal(t, expectedBodyString, bodyString)
}
})
t.Run("Config with aunitconfig-yml mps", func(t *testing.T) {
config := abapEnvironmentRunAUnitTestOptions{
AUnitResultsFileName: "aUnitResults.xml",
AUnitConfig: "aunit.yml",
}
dir := t.TempDir()
oldCWD, _ := os.Getwd()
_ = os.Chdir(dir)
// clean up tmp dir
defer func() {
_ = os.Chdir(oldCWD)
}()
yamlBody := `title: My AUnit run
objectset:
type: multiPropertySet
multipropertyset:
packages:
- name: Z_TEST
softwarecomponents:
- name: Z_TEST
- name: /DMO/SWC
`
expectedBodyString := ""
err := os.WriteFile(config.AUnitConfig, []byte(yamlBody), 0o644)
if assert.Equal(t, err, nil) {
bodyString, err := buildAUnitRequestBody(config)
assert.Equal(t, nil, err)
assert.Equal(t, expectedBodyString, bodyString)
}
})
t.Run("No AUnit config file - expect no panic", func(t *testing.T) {
config := abapEnvironmentRunAUnitTestOptions{
AUnitConfig: "aunit.yml",
}
_, err := buildAUnitRequestBody(config)
assert.Equal(t, "Could not find aunit.yml", err.Error())
})
t.Run("No Repo config file - expect no panic", func(t *testing.T) {
config := abapEnvironmentRunAUnitTestOptions{
Repositories: "repo.yml",
}
_, err := buildAUnitRequestBody(config)
assert.Equal(t, "Could not find repo.yml", err.Error())
})
}
func TestTriggerAUnitrun(t *testing.T) {
t.Run("succes case: test parsing example yaml config", func(t *testing.T) {
config := abapEnvironmentRunAUnitTestOptions{
AUnitConfig: "aUnitConfig.yml",
AUnitResultsFileName: "aUnitResults.xml",
}
client := &abaputils.ClientMock{
Body: `AUnit test result body`,
StatusCode: 200,
}
con := abaputils.ConnectionDetailsHTTP{
User: "Test",
Password: "Test",
URL: "https://api.endpoint.com/Entity/",
}
dir := t.TempDir()
oldCWD, _ := os.Getwd()
_ = os.Chdir(dir)
// clean up tmp dir
defer func() {
_ = os.Chdir(oldCWD)
}()
yamlBody := `title: My AUnit run
context: AIE integration tests
options:
measurements: none
scope:
owntests: true
foreigntests: true
riskLevel:
harmless: true
dangerous: true
critical: true
duration:
short: true
medium: true
long: true
objectset:
packages:
- name: Z_TEST
softwarecomponents:
- name: Z_TEST
`
err := os.WriteFile(config.AUnitConfig, []byte(yamlBody), 0o644)
if assert.Equal(t, err, nil) {
_, err := triggerAUnitrun(config, con, client)
assert.Equal(t, nil, err)
}
})
t.Run("succes case: test parsing example yaml config", func(t *testing.T) {
config := abapEnvironmentRunAUnitTestOptions{
AUnitConfig: "aUnitConfig.yml",
AUnitResultsFileName: "aUnitResults.xml",
}
client := &abaputils.ClientMock{
Body: `AUnit test result body`,
}
con := abaputils.ConnectionDetailsHTTP{
User: "Test",
Password: "Test",
URL: "https://api.endpoint.com/Entity/",
}
dir := t.TempDir()
oldCWD, _ := os.Getwd()
_ = os.Chdir(dir)
// clean up tmp dir
defer func() {
_ = os.Chdir(oldCWD)
}()
yamlBody := `title: My AUnit run
context: AIE integration tests
options:
measurements: none
scope:
owntests: true
foreigntests: true
riskLevel:
harmless: true
dangerous: true
critical: true
duration:
short: true
medium: true
long: true
objectset:
type: unionSet
set:
- type: componentSet
component:
- name: Z_TEST_SC
`
err := os.WriteFile(config.AUnitConfig, []byte(yamlBody), 0o644)
if assert.Equal(t, err, nil) {
_, err := triggerAUnitrun(config, con, client)
assert.Equal(t, nil, err)
}
})
}
func TestParseAUnitResult(t *testing.T) {
t.Parallel()
t.Run("succes case: test parsing example XML result", func(t *testing.T) {
bodyString := `Test1Test2`
body := []byte(bodyString)
err := persistAUnitResult(&mock.FilesMock{}, body, "AUnitResults.xml", false)
assert.Equal(t, nil, err)
})
t.Run("succes case: test parsing empty AUnit run XML result", func(t *testing.T) {
bodyString := ``
body := []byte(bodyString)
err := persistAUnitResult(&mock.FilesMock{}, body, "AUnitResults.xml", false)
assert.Equal(t, nil, err)
})
t.Run("failure case: parsing empty xml", func(t *testing.T) {
var bodyString string
body := []byte(bodyString)
err := persistAUnitResult(&mock.FilesMock{}, body, "AUnitResults.xml", false)
assert.EqualError(t, err, "Parsing AUnit result failed: Body is empty, can't parse empty body")
})
}
func TestGetResultAUnitRun(t *testing.T) {
t.Parallel()
t.Run("Get HTTP Response from AUnit test run Test", func(t *testing.T) {
t.Parallel()
client := &abaputils.ClientMock{
Body: `AUnit test result body`,
}
con := abaputils.ConnectionDetailsHTTP{
User: "Test",
Password: "Test",
URL: "https://api.endpoint.com/Entity/",
}
resp, err := getAUnitResults("GET", con, []byte(client.Body), client)
assert.NoError(t, err)
defer resp.Body.Close()
if assert.Equal(t, nil, err) {
buf := new(bytes.Buffer)
_, err = buf.ReadFrom(resp.Body)
assert.NoError(t, err)
newStr := buf.String()
assert.Equal(t, "AUnit test result body", newStr)
assert.Equal(t, int64(0), resp.ContentLength)
assert.Equal(t, []string([]string(nil)), resp.Header["X-Crsf-Token"])
}
})
t.Run("Get HTTP Response from AUnit test run Test Failure", func(t *testing.T) {
t.Parallel()
client := &abaputils.ClientMock{
Body: `AUnit test result body`,
BodyList: []string{},
StatusCode: 400,
Error: fmt.Errorf("%w", errors.New("Test fail")),
}
con := abaputils.ConnectionDetailsHTTP{
User: "Test",
Password: "Test",
URL: "https://api.endpoint.com/Entity/",
}
resp, err := getAUnitResults("GET", con, []byte(client.Body), client)
assert.EqualError(t, err, "Getting AUnit run results failed: Test fail")
defer resp.Body.Close()
buf := new(bytes.Buffer)
_, err = buf.ReadFrom(resp.Body)
assert.NoError(t, err)
newStr := buf.String()
assert.Equal(t, "AUnit test result body", newStr)
assert.Equal(t, int64(0), resp.ContentLength)
assert.Equal(t, 400, resp.StatusCode)
assert.Equal(t, []string([]string(nil)), resp.Header["X-Crsf-Token"])
})
}
func TestRunAbapEnvironmentRunAUnitTest(t *testing.T) {
t.Parallel()
t.Run("FetchXcsrfToken Test", func(t *testing.T) {
t.Parallel()
tokenExpected := "myToken"
client := &abaputils.ClientMock{
Body: `Xcsrf Token test`,
Token: tokenExpected,
}
con := abaputils.ConnectionDetailsHTTP{
User: "Test",
Password: "Test",
URL: "https://api.endpoint.com/Entity/",
}
token, error := fetchAUnitXcsrfToken("GET", con, []byte(client.Body), client)
if assert.Equal(t, nil, error) {
assert.Equal(t, tokenExpected, token)
}
})
t.Run("failure case: fetch token", func(t *testing.T) {
t.Parallel()
tokenExpected := ""
client := &abaputils.ClientMock{
Body: `Xcsrf Token test`,
Token: "",
}
con := abaputils.ConnectionDetailsHTTP{
User: "Test",
Password: "Test",
URL: "https://api.endpoint.com/Entity/",
}
token, error := fetchAUnitXcsrfToken("GET", con, []byte(client.Body), client)
if assert.Equal(t, nil, error) {
assert.Equal(t, tokenExpected, token)
}
})
t.Run("AUnit test run Poll Test", func(t *testing.T) {
t.Parallel()
tokenExpected := "myToken"
client := &abaputils.ClientMock{
Body: ``,
Token: tokenExpected,
}
con := abaputils.ConnectionDetailsHTTP{
User: "Test",
Password: "Test",
URL: "https://api.endpoint.com/Entity/",
}
resp, err := pollAUnitRun(con, []byte(client.Body), client)
if assert.Equal(t, nil, err) {
assert.Equal(t, "/sap/bc/adt/api/abapunit/results/test", resp)
}
})
t.Run("AUnit test run Poll Test Fail", func(t *testing.T) {
t.Parallel()
tokenExpected := "myToken"
client := &abaputils.ClientMock{
Body: ``,
Token: tokenExpected,
}
con := abaputils.ConnectionDetailsHTTP{
User: "Test",
Password: "Test",
URL: "https://api.endpoint.com/Entity/",
}
resp, err := pollAUnitRun(con, []byte(client.Body), client)
if assert.Equal(t, nil, err) {
assert.Equal(t, "", resp)
}
})
t.Run("Get HTTP Response from AUnit test run Test", func(t *testing.T) {
t.Parallel()
client := &abaputils.ClientMock{
Body: `HTTP response test`,
}
con := abaputils.ConnectionDetailsHTTP{
User: "Test",
Password: "Test",
URL: "https://api.endpoint.com/Entity/",
}
fmt.Println("Body:" + string([]byte(client.Body)))
resp, err := getHTTPResponseAUnitRun("GET", con, []byte(client.Body), client)
assert.NoError(t, err)
defer resp.Body.Close()
if assert.Equal(t, nil, err) {
buf := new(bytes.Buffer)
_, err = buf.ReadFrom(resp.Body)
assert.NoError(t, err)
newStr := buf.String()
assert.Equal(t, "HTTP response test", newStr)
assert.Equal(t, int64(0), resp.ContentLength)
assert.Equal(t, []string([]string(nil)), resp.Header["X-Crsf-Token"])
}
})
}
func TestGenerateHTMLDocumentAUnit(t *testing.T) {
t.Run("Test empty XML Result", func(t *testing.T) {
expectedString := `
AUnit ResultsAUnit Results
Run title | | System | | Client | | ExecutedBy | | Duration | s | Timestamp | |
---|
Failures | | Errors | | Skipped | | Asserts | | Tests | |
---|
Severity | File | Message | Type | Text |
---|
There are no AUnit findings to be displayed |
`
result := AUnitResult{}
resultString := generateHTMLDocumentAUnit(&result)
assert.Equal(t, expectedString, resultString)
})
t.Run("Test AUnit XML Result", func(t *testing.T) {
expectedString := `AUnit ResultsAUnit Results
Run title | Test title | System | Test system | Client | 000 | ExecutedBy | CC00000 | Duration | 0.15s | Timestamp | 2021-00-00T00:00:00Z |
---|
Failures | 4 | Errors | 4 | Skipped | 4 | Asserts | 12 | Tests | 12 |
---|
Severity | File | Message | Type | Text |
---|
Testcase: my_test for class ZCL_my_test |
Failure | ZCL_my_test | testMessage | Assert Error | testError |
Failure | ZCL_my_test | testMessage2 | Assert Error2 | testError2 |
Failure | ZCL_my_test | testMessage | Assert Failure | testFailure |
Failure | ZCL_my_test | testMessage2 | Assert Failure2 | testFailure2 |
Failure | ZCL_my_test | testSkipped | - | testSkipped |
Failure | ZCL_my_test | testSkipped2 | - | testSkipped2 |
Testcase: my_test2 for class ZCL_my_test2 |
Failure | ZCL_my_test2 | testMessage3 | Assert Error3 | testError3 |
Failure | ZCL_my_test2 | testMessage4 | Assert Error4 | testError4 |
Failure | ZCL_my_test2 | testMessage5 | Assert Failure5 | testFailure5 |
Failure | ZCL_my_test2 | testMessage6 | Assert Failure6 | testFailure6 |
Failure | ZCL_my_test2 | testSkipped7 | - | testSkipped7 |
Failure | ZCL_my_test2 | testSkipped8 | - | testSkipped8 |
`
result := AUnitResult{
XMLName: xml.Name{Space: "testSpace", Local: "testLocal"},
Title: "Test title",
System: "Test system",
Client: "000",
ExecutedBy: "CC00000",
Time: "0.15",
Timestamp: "2021-00-00T00:00:00Z",
Failures: "4",
Errors: "4",
Skipped: "4",
Asserts: "12",
Tests: "12",
Testsuite: struct {
Tests string `xml:"tests,attr"`
Asserts string `xml:"asserts,attr"`
Skipped string `xml:"skipped,attr"`
Errors string `xml:"errors,attr"`
Failures string `xml:"failures,attr"`
Timestamp string `xml:"timestamp,attr"`
Time string `xml:"time,attr"`
Hostname string `xml:"hostname,attr"`
Package string `xml:"package,attr"`
Name string `xml:"name,attr"`
Testcase []struct {
Asserts string `xml:"asserts,attr"`
Time string `xml:"time,attr"`
Name string `xml:"name,attr"`
Classname string `xml:"classname,attr"`
Error []struct {
Text string `xml:",chardata"`
Type string `xml:"type,attr"`
Message string `xml:"message,attr"`
} `xml:"error"`
Failure []struct {
Text string `xml:",chardata"`
Type string `xml:"type,attr"`
Message string `xml:"message,attr"`
} `xml:"failure"`
Skipped []struct {
Text string `xml:",chardata"`
Message string `xml:"message,attr"`
} `xml:"skipped"`
} `xml:"testcase"`
}{
Tests: "6",
Asserts: "4",
Skipped: "2",
Errors: "2",
Failures: "2",
Timestamp: "2021-00-00T00:00:00Z",
Time: "0.15",
Hostname: "0xb",
Package: "testPackage",
Name: "ZCL_testPackage",
Testcase: []struct {
Asserts string "xml:\"asserts,attr\""
Time string "xml:\"time,attr\""
Name string "xml:\"name,attr\""
Classname string "xml:\"classname,attr\""
Error []struct {
Text string "xml:\",chardata\""
Type string "xml:\"type,attr\""
Message string "xml:\"message,attr\""
} "xml:\"error\""
Failure []struct {
Text string "xml:\",chardata\""
Type string "xml:\"type,attr\""
Message string "xml:\"message,attr\""
} "xml:\"failure\""
Skipped []struct {
Text string "xml:\",chardata\""
Message string "xml:\"message,attr\""
} "xml:\"skipped\""
}{{
Asserts: "4",
Time: "0.15",
Name: "my_test",
Classname: "ZCL_my_test",
Error: []struct {
Text string "xml:\",chardata\""
Type string "xml:\"type,attr\""
Message string "xml:\"message,attr\""
}{{
Text: "testError",
Type: "Assert Error",
Message: "testMessage",
}, {
Text: "testError2",
Type: "Assert Error2",
Message: "testMessage2",
}},
Failure: []struct {
Text string "xml:\",chardata\""
Type string "xml:\"type,attr\""
Message string "xml:\"message,attr\""
}{{
Text: "testFailure",
Type: "Assert Failure",
Message: "testMessage",
}, {
Text: "testFailure2",
Type: "Assert Failure2",
Message: "testMessage2",
}},
Skipped: []struct {
Text string "xml:\",chardata\""
Message string "xml:\"message,attr\""
}{{
Text: "testSkipped",
Message: "testSkipped",
}, {
Text: "testSkipped2",
Message: "testSkipped2",
}},
}, {
Asserts: "4",
Time: "0.15",
Name: "my_test2",
Classname: "ZCL_my_test2",
Error: []struct {
Text string "xml:\",chardata\""
Type string "xml:\"type,attr\""
Message string "xml:\"message,attr\""
}{{
Text: "testError3",
Type: "Assert Error3",
Message: "testMessage3",
}, {
Text: "testError4",
Type: "Assert Error4",
Message: "testMessage4",
}},
Failure: []struct {
Text string "xml:\",chardata\""
Type string "xml:\"type,attr\""
Message string "xml:\"message,attr\""
}{{
Text: "testFailure5",
Type: "Assert Failure5",
Message: "testMessage5",
}, {
Text: "testFailure6",
Type: "Assert Failure6",
Message: "testMessage6",
}},
Skipped: []struct {
Text string "xml:\",chardata\""
Message string "xml:\"message,attr\""
}{{
Text: "testSkipped7",
Message: "testSkipped7",
}, {
Text: "testSkipped8",
Message: "testSkipped8",
}},
}},
},
}
resultString := generateHTMLDocumentAUnit(&result)
fmt.Println(resultString)
assert.Equal(t, expectedString, resultString)
})
}