1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2025-11-06 09:09:19 +02:00

Add easy mode for AUnit & ATC (#3389)

* remove mandatory flag from config files

* Enable repo.yml as config

* Adapt to merge

* Refactoring

* Refactoring

* avoid panic

* Add comments

* Add easy mode for atc

* Add tests

* Add test

* Refactor

* Add test for MPS

* Updates

* Rename functions

* Add files to gitignore

* Rename

* Renaming

* Renaming

* Renaming

* Improve error messages

* Update documentation

* Add logging

* Rename

* Extend gitignore
This commit is contained in:
Daniel Mieg
2022-01-12 12:02:27 +01:00
committed by GitHub
parent 24a2340921
commit 8634d8bb12
14 changed files with 528 additions and 366 deletions

View File

@@ -8,7 +8,6 @@ import (
"io/ioutil"
"net/http"
"net/http/cookiejar"
"path/filepath"
"strconv"
"strings"
"time"
@@ -19,7 +18,6 @@ import (
"github.com/SAP/jenkins-library/pkg/log"
"github.com/SAP/jenkins-library/pkg/piperutils"
"github.com/SAP/jenkins-library/pkg/telemetry"
"github.com/ghodss/yaml"
"github.com/pkg/errors"
)
@@ -61,10 +59,10 @@ func abapEnvironmentRunATCCheck(options abapEnvironmentRunATCCheckOptions, telem
details.XCsrfToken, err = fetchXcsrfToken("GET", details, nil, &client)
}
if err == nil {
resp, err = triggerATCrun(options, details, &client)
resp, err = triggerATCRun(options, details, &client)
}
if err == nil {
err = handleATCresults(resp, details, &client, options.AtcResultsFileName, options.GenerateHTML)
err = fetchAndPersistATCResults(resp, details, &client, options.AtcResultsFileName, options.GenerateHTML)
}
if err != nil {
log.Entry().WithError(err).Fatal("step execution failed")
@@ -73,7 +71,7 @@ func abapEnvironmentRunATCCheck(options abapEnvironmentRunATCCheckOptions, telem
log.Entry().Info("ATC run completed successfully. If there are any results from the respective run they will be listed in the logs above as well as being saved in the output .xml file")
}
func handleATCresults(resp *http.Response, details abaputils.ConnectionDetailsHTTP, client piperhttp.Sender, atcResultFileName string, generateHTML bool) error {
func fetchAndPersistATCResults(resp *http.Response, details abaputils.ConnectionDetailsHTTP, client piperhttp.Sender, atcResultFileName string, generateHTML bool) error {
var err error
var abapEndpoint string
abapEndpoint = details.URL
@@ -91,7 +89,7 @@ func handleATCresults(resp *http.Response, details abaputils.ConnectionDetailsHT
}
if err == nil {
defer resp.Body.Close()
err = parseATCResult(body, atcResultFileName, generateHTML)
err = logAndPersistATCResult(body, atcResultFileName, generateHTML)
}
if err != nil {
return fmt.Errorf("Handling ATC result failed: %w", err)
@@ -99,83 +97,107 @@ func handleATCresults(resp *http.Response, details abaputils.ConnectionDetailsHT
return nil
}
func triggerATCrun(config abapEnvironmentRunATCCheckOptions, details abaputils.ConnectionDetailsHTTP, client piperhttp.Sender) (*http.Response, error) {
var atcConfigyamlFile []byte
abapEndpoint := details.URL
filelocation, err := filepath.Glob(config.AtcConfig)
//Parse YAML ATC run configuration as body for ATC run trigger
if err == nil {
filename, err := filepath.Abs(filelocation[0])
if err == nil {
atcConfigyamlFile, err = ioutil.ReadFile(filename)
}
}
var ATCConfig ATCconfig
if err == nil {
var result []byte
result, err = yaml.YAMLToJSON(atcConfigyamlFile)
json.Unmarshal(result, &ATCConfig)
}
var checkVariantString, packageString, softwareComponentString string
if err == nil {
checkVariantString, packageString, softwareComponentString, err = buildATCCheckBody(ATCConfig)
}
func triggerATCRun(config abapEnvironmentRunATCCheckOptions, details abaputils.ConnectionDetailsHTTP, client piperhttp.Sender) (*http.Response, error) {
//Trigger ATC run
bodyString, err := buildATCRequestBody(config)
if err != nil {
return nil, err
}
var resp *http.Response
var bodyString = `<?xml version="1.0" encoding="UTF-8"?><atc:runparameters xmlns:atc="http://www.sap.com/adt/atc" xmlns:obj="http://www.sap.com/adt/objectset"` + checkVariantString + `><obj:objectSet>` + softwareComponentString + packageString + `</obj:objectSet></atc:runparameters>`
abapEndpoint := details.URL
log.Entry().Debugf("Request Body: %s", bodyString)
var body = []byte(bodyString)
if err == nil {
details.URL = abapEndpoint + "/sap/bc/adt/api/atc/runs?clientWait=false"
resp, err = runATC("POST", details, body, client)
}
if err != nil {
return resp, fmt.Errorf("Triggering ATC run failed: %w", err)
}
return resp, nil
details.URL = abapEndpoint + "/sap/bc/adt/api/atc/runs?clientWait=false"
resp, err = runATC("POST", details, body, client)
return resp, err
}
func buildATCCheckBody(ATCConfig ATCconfig) (checkVariantString string, packageString string, softwareComponentString string, err error) {
if len(ATCConfig.Objects.Package) == 0 && len(ATCConfig.Objects.SoftwareComponent) == 0 {
log.SetErrorCategory(log.ErrorConfiguration)
return "", "", "", fmt.Errorf("Error while parsing ATC run config. Please provide the packages and/or the software components to be checked! %w", errors.New("No Package or Software Component specified. Please provide either one or both of them"))
func buildATCRequestBody(config abapEnvironmentRunATCCheckOptions) (bodyString string, err error) {
atcConfig, err := resolveATCConfiguration(config)
if err != nil {
return "", err
}
//Build Check Variant and Configuration XML Body
if len(ATCConfig.CheckVariant) != 0 {
checkVariantString += ` checkVariant="` + ATCConfig.CheckVariant + `"`
log.Entry().Infof("ATC Check Variant: %s", ATCConfig.CheckVariant)
if len(ATCConfig.Configuration) != 0 {
checkVariantString += ` configuration="` + ATCConfig.Configuration + `"`
// Create string for the run parameters
variant := "ABAP_CLOUD_DEVELOPMENT_DEFAULT"
if atcConfig.CheckVariant != "" {
variant = atcConfig.CheckVariant
}
log.Entry().Infof("ATC Check Variant: %s", variant)
runParameters := ` checkVariant="` + variant + `"`
if atcConfig.Configuration != "" {
runParameters += ` configuration="` + atcConfig.Configuration + `"`
}
objectSet, err := getATCObjectSet(atcConfig)
bodyString = `<?xml version="1.0" encoding="UTF-8"?><atc:runparameters xmlns:atc="http://www.sap.com/adt/atc" xmlns:obj="http://www.sap.com/adt/objectset"` + runParameters + `>` + objectSet + `</atc:runparameters>`
return bodyString, err
}
func resolveATCConfiguration(config abapEnvironmentRunATCCheckOptions) (atcConfig ATCConfiguration, err error) {
if config.AtcConfig != "" {
// Configuration defaults to AUnitConfig
log.Entry().Infof("ATC Configuration: %s", config.AtcConfig)
atcConfigFile, err := abaputils.ReadConfigFile(config.AtcConfig)
if err != nil {
return atcConfig, err
}
json.Unmarshal(atcConfigFile, &atcConfig)
return atcConfig, err
} else if config.Repositories != "" {
// Fallback / EasyMode is the Repositories configuration
log.Entry().Infof("ATC Configuration derived from: %s", config.Repositories)
repositories, err := abaputils.GetRepositories((&abaputils.RepositoriesConfig{Repositories: config.Repositories}))
if err != nil {
return atcConfig, err
}
for _, repository := range repositories {
atcConfig.Objects.SoftwareComponent = append(atcConfig.Objects.SoftwareComponent, SoftwareComponent{Name: repository.Name})
}
return atcConfig, nil
} else {
const defaultCheckVariant = "ABAP_CLOUD_DEVELOPMENT_DEFAULT"
checkVariantString += ` checkVariant="` + defaultCheckVariant + `"`
log.Entry().Infof("ATC Check Variant: %s", checkVariantString)
// Fail if no configuration is provided
return atcConfig, errors.New("No configuration provided - please provide either an ATC configuration file or a repository configuration file")
}
}
func getATCObjectSet(ATCConfig ATCConfiguration) (objectSet string, err error) {
if len(ATCConfig.Objects.Package) == 0 && len(ATCConfig.Objects.SoftwareComponent) == 0 {
log.SetErrorCategory(log.ErrorConfiguration)
return "", fmt.Errorf("Error while parsing ATC run config. Please provide the packages and/or the software components to be checked! %w", errors.New("No Package or Software Component specified. Please provide either one or both of them"))
}
objectSet += `<obj:objectSet>`
//Build SC XML body
if len(ATCConfig.Objects.SoftwareComponent) != 0 {
objectSet += "<obj:softwarecomponents>"
for _, s := range ATCConfig.Objects.SoftwareComponent {
objectSet += `<obj:softwarecomponent value="` + s.Name + `"/>`
}
objectSet += "</obj:softwarecomponents>"
}
//Build Package XML body
if len(ATCConfig.Objects.Package) != 0 {
packageString += "<obj:packages>"
objectSet += "<obj:packages>"
for _, s := range ATCConfig.Objects.Package {
packageString += `<obj:package value="` + s.Name + `" includeSubpackages="` + strconv.FormatBool(s.IncludeSubpackages) + `"/>`
objectSet += `<obj:package value="` + s.Name + `" includeSubpackages="` + strconv.FormatBool(s.IncludeSubpackages) + `"/>`
}
packageString += "</obj:packages>"
objectSet += "</obj:packages>"
}
//Build SC XML body
if len(ATCConfig.Objects.SoftwareComponent) != 0 {
softwareComponentString += "<obj:softwarecomponents>"
for _, s := range ATCConfig.Objects.SoftwareComponent {
softwareComponentString += `<obj:softwarecomponent value="` + s.Name + `"/>`
}
softwareComponentString += "</obj:softwarecomponents>"
}
return checkVariantString, packageString, softwareComponentString, nil
objectSet += `</obj:objectSet>`
return objectSet, nil
}
func parseATCResult(body []byte, atcResultFileName string, generateHTML bool) (err error) {
func logAndPersistATCResult(body []byte, atcResultFileName string, generateHTML bool) (err error) {
if len(body) == 0 {
return fmt.Errorf("Parsing ATC result failed: %w", errors.New("Body is empty, can't parse empty body"))
}
@@ -253,9 +275,6 @@ func fetchXcsrfToken(requestType string, details abaputils.ConnectionDetailsHTTP
}
defer req.Body.Close()
// workaround until golang version 1.16 is used
time.Sleep(1 * time.Second)
token := req.Header.Get("X-Csrf-Token")
return token, err
}
@@ -293,8 +312,6 @@ func pollATCRun(details abaputils.ConnectionDetailsHTTP, body []byte, client pip
func getHTTPResponseATCRun(requestType string, details abaputils.ConnectionDetailsHTTP, body []byte, client piperhttp.Sender) (*http.Response, error) {
log.Entry().WithField("ABAP Endpoint: ", details.URL).Info("Polling ATC run status")
header := make(map[string][]string)
header["Accept"] = []string{"application/vnd.sap.atc.run.v1+xml"}
@@ -364,8 +381,8 @@ func generateHTMLDocument(parsedXML *Result) (htmlDocumentString string) {
return htmlDocumentString
}
//ATCconfig object for parsing yaml config of software components and packages
type ATCconfig struct {
//ATCConfiguration object for parsing yaml config of software components and packages
type ATCConfiguration struct {
CheckVariant string `json:"checkvariant,omitempty"`
Configuration string `json:"configuration,omitempty"`
Objects ATCObjects `json:"atcobjects"`

View File

@@ -17,6 +17,7 @@ import (
type abapEnvironmentRunATCCheckOptions struct {
AtcConfig string `json:"atcConfig,omitempty"`
Repositories string `json:"repositories,omitempty"`
CfAPIEndpoint string `json:"cfApiEndpoint,omitempty"`
CfOrg string `json:"cfOrg,omitempty"`
CfServiceInstance string `json:"cfServiceInstance,omitempty"`
@@ -128,6 +129,7 @@ Regardless of the option you chose, please make sure to provide the configuratio
func addAbapEnvironmentRunATCCheckFlags(cmd *cobra.Command, stepConfig *abapEnvironmentRunATCCheckOptions) {
cmd.Flags().StringVar(&stepConfig.AtcConfig, "atcConfig", os.Getenv("PIPER_atcConfig"), "Path to a YAML configuration file for Packages and/or Software Components to be checked during ATC run")
cmd.Flags().StringVar(&stepConfig.Repositories, "repositories", os.Getenv("PIPER_repositories"), "Specifies a YAML file containing the repositories configuration")
cmd.Flags().StringVar(&stepConfig.CfAPIEndpoint, "cfApiEndpoint", os.Getenv("PIPER_cfApiEndpoint"), "Cloud Foundry API endpoint")
cmd.Flags().StringVar(&stepConfig.CfOrg, "cfOrg", os.Getenv("PIPER_cfOrg"), "CF org")
cmd.Flags().StringVar(&stepConfig.CfServiceInstance, "cfServiceInstance", os.Getenv("PIPER_cfServiceInstance"), "Parameter of ServiceInstance Name to delete CloudFoundry Service")
@@ -139,7 +141,6 @@ func addAbapEnvironmentRunATCCheckFlags(cmd *cobra.Command, stepConfig *abapEnvi
cmd.Flags().StringVar(&stepConfig.AtcResultsFileName, "atcResultsFileName", `ATCResults.xml`, "Specifies output file name for the results from the ATC run. This file name will also be used for generating the HTML file")
cmd.Flags().BoolVar(&stepConfig.GenerateHTML, "generateHTML", false, "Specifies whether the ATC results should also be generated as an HTML document")
cmd.MarkFlagRequired("atcConfig")
cmd.MarkFlagRequired("username")
cmd.MarkFlagRequired("password")
}
@@ -163,10 +164,19 @@ func abapEnvironmentRunATCCheckMetadata() config.StepData {
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: true,
Mandatory: false,
Aliases: []config.Alias{},
Default: os.Getenv("PIPER_atcConfig"),
},
{
Name: "repositories",
ResourceRef: []config.ResourceReference{},
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
Default: os.Getenv("PIPER_repositories"),
},
{
Name: "cfApiEndpoint",
ResourceRef: []config.ResourceReference{},

View File

@@ -248,7 +248,7 @@ func TestParseATCResult(t *testing.T) {
</file>
</checkstyle>`
body := []byte(bodyString)
err = parseATCResult(body, "ATCResults.xml", false)
err = logAndPersistATCResult(body, "ATCResults.xml", false)
assert.Equal(t, nil, err)
})
t.Run("succes case: test parsing empty XML result", func(t *testing.T) {
@@ -267,14 +267,14 @@ func TestParseATCResult(t *testing.T) {
<checkstyle>
</checkstyle>`
body := []byte(bodyString)
err = parseATCResult(body, "ATCResults.xml", false)
err = logAndPersistATCResult(body, "ATCResults.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 := parseATCResult(body, "ATCResults.xml", false)
err := logAndPersistATCResult(body, "ATCResults.xml", false)
assert.EqualError(t, err, "Parsing ATC result failed: Body is empty, can't parse empty body")
})
t.Run("failure case: html response", func(t *testing.T) {
@@ -291,37 +291,27 @@ func TestParseATCResult(t *testing.T) {
}()
bodyString := `<html><head><title>HTMLTestResponse</title</head></html>`
body := []byte(bodyString)
err = parseATCResult(body, "ATCResults.xml", false)
err = logAndPersistATCResult(body, "ATCResults.xml", false)
assert.EqualError(t, err, "The Software Component could not be checked. Please make sure the respective Software Component has been cloned successfully on the system")
})
}
func TestBuildATCCheckBody(t *testing.T) {
t.Run("Test build body with no software component and package", func(t *testing.T) {
expectedpackagestring := ""
expectedsoftwarecomponentstring := ""
expectedcheckvariantstring := ""
expectedObjectSet := ""
var err error
var config ATCconfig
var checkVariantString, packageString, softwarecomponentString string
var config ATCConfiguration
checkVariantString, packageString, softwarecomponentString, err = buildATCCheckBody(config)
objectSet, err := getATCObjectSet(config)
assert.Equal(t, expectedcheckvariantstring, checkVariantString)
assert.Equal(t, expectedpackagestring, packageString)
assert.Equal(t, expectedsoftwarecomponentstring, softwarecomponentString)
assert.Equal(t, expectedObjectSet, objectSet)
assert.EqualError(t, err, "Error while parsing ATC run config. Please provide the packages and/or the software components to be checked! No Package or Software Component specified. Please provide either one or both of them")
})
t.Run("success case: Test build body with example yaml config", func(t *testing.T) {
expectedcheckvariantstring := " checkVariant=\"ABAP_CLOUD_DEVELOPMENT_DEFAULT\""
expectedpackagestring := "<obj:packages><obj:package value=\"testPackage\" includeSubpackages=\"true\"/><obj:package value=\"testPackage2\" includeSubpackages=\"false\"/></obj:packages>"
expectedsoftwarecomponentstring := "<obj:softwarecomponents><obj:softwarecomponent value=\"testSoftwareComponent\"/><obj:softwarecomponent value=\"testSoftwareComponent2\"/></obj:softwarecomponents>"
var err error
var config ATCconfig
expectedObjectSet := "<obj:objectSet><obj:softwarecomponents><obj:softwarecomponent value=\"testSoftwareComponent\"/><obj:softwarecomponent value=\"testSoftwareComponent2\"/></obj:softwarecomponents><obj:packages><obj:package value=\"testPackage\" includeSubpackages=\"true\"/><obj:package value=\"testPackage2\" includeSubpackages=\"false\"/></obj:packages></obj:objectSet>"
config = ATCconfig{
config := ATCConfiguration{
"",
"",
ATCObjects{
@@ -336,24 +326,19 @@ func TestBuildATCCheckBody(t *testing.T) {
},
}
var checkvariantString, packageString, softwarecomponentString string
objectSet, err := getATCObjectSet(config)
checkvariantString, packageString, softwarecomponentString, err = buildATCCheckBody(config)
assert.Equal(t, expectedcheckvariantstring, checkvariantString)
assert.Equal(t, expectedpackagestring, packageString)
assert.Equal(t, expectedsoftwarecomponentstring, softwarecomponentString)
assert.Equal(t, expectedObjectSet, objectSet)
assert.Equal(t, nil, err)
})
t.Run("failure case: Test build body with example yaml config with only packages and no software components", func(t *testing.T) {
expectedcheckvariantstring := " checkVariant=\"ABAP_CLOUD_DEVELOPMENT_DEFAULT\""
expectedpackagestring := `<obj:packages><obj:package value="testPackage" includeSubpackages="true"/><obj:package value="testPackage2" includeSubpackages="false"/></obj:packages>`
expectedsoftwarecomponentstring := ""
expectedObjectSet := `<obj:objectSet><obj:packages><obj:package value="testPackage" includeSubpackages="true"/><obj:package value="testPackage2" includeSubpackages="false"/></obj:packages></obj:objectSet>`
var err error
var config ATCconfig
var config ATCConfiguration
config = ATCconfig{
config = ATCConfiguration{
"",
"",
ATCObjects{
@@ -364,25 +349,17 @@ func TestBuildATCCheckBody(t *testing.T) {
},
}
var checkvariantString, packageString, softwarecomponentString string
objectSet, err := getATCObjectSet(config)
checkvariantString, packageString, softwarecomponentString, err = buildATCCheckBody(config)
assert.Equal(t, expectedcheckvariantstring, checkvariantString)
assert.Equal(t, expectedpackagestring, packageString)
assert.Equal(t, expectedsoftwarecomponentstring, softwarecomponentString)
assert.Equal(t, expectedObjectSet, objectSet)
assert.Equal(t, nil, err)
})
t.Run("success case: Test build body with example yaml config with no packages and only software components", func(t *testing.T) {
expectedcheckvariantstring := " checkVariant=\"ABAP_CLOUD_DEVELOPMENT_DEFAULT\""
expectedpackagestring := ""
expectedsoftwarecomponentstring := `<obj:softwarecomponents><obj:softwarecomponent value="testSoftwareComponent"/><obj:softwarecomponent value="testSoftwareComponent2"/></obj:softwarecomponents>`
var err error
var config ATCconfig
expectedObjectSet := `<obj:objectSet><obj:softwarecomponents><obj:softwarecomponent value="testSoftwareComponent"/><obj:softwarecomponent value="testSoftwareComponent2"/></obj:softwarecomponents></obj:objectSet>`
config = ATCconfig{
config := ATCConfiguration{
"",
"",
ATCObjects{
@@ -393,45 +370,9 @@ func TestBuildATCCheckBody(t *testing.T) {
},
}
var checkvariantString, packageString, softwarecomponentString string
objectSet, err := getATCObjectSet(config)
checkvariantString, packageString, softwarecomponentString, err = buildATCCheckBody(config)
assert.Equal(t, expectedcheckvariantstring, checkvariantString)
assert.Equal(t, expectedpackagestring, packageString)
assert.Equal(t, expectedsoftwarecomponentstring, softwarecomponentString)
assert.Equal(t, nil, err)
})
t.Run("success case: Test build body with example yaml config with check variant configuration", func(t *testing.T) {
expectedcheckvariantstring := ` checkVariant="TestVariant" configuration="TestConfiguration"`
expectedpackagestring := `<obj:packages><obj:package value="testPackage" includeSubpackages="true"/><obj:package value="testPackage2" includeSubpackages="false"/></obj:packages>`
expectedsoftwarecomponentstring := `<obj:softwarecomponents><obj:softwarecomponent value="testSoftwareComponent"/><obj:softwarecomponent value="testSoftwareComponent2"/></obj:softwarecomponents>`
var err error
var config ATCconfig
config = ATCconfig{
"TestVariant",
"TestConfiguration",
ATCObjects{
SoftwareComponent: []SoftwareComponent{
{Name: "testSoftwareComponent"},
{Name: "testSoftwareComponent2"},
},
Package: []Package{
{Name: "testPackage", IncludeSubpackages: true},
{Name: "testPackage2", IncludeSubpackages: false},
},
},
}
var checkvariantString, packageString, softwarecomponentString string
checkvariantString, packageString, softwarecomponentString, err = buildATCCheckBody(config)
assert.Equal(t, expectedcheckvariantstring, checkvariantString)
assert.Equal(t, expectedpackagestring, packageString)
assert.Equal(t, expectedsoftwarecomponentstring, softwarecomponentString)
assert.Equal(t, expectedObjectSet, objectSet)
assert.Equal(t, nil, err)
})
}
@@ -463,3 +404,99 @@ func TestGenerateHTMLDocument(t *testing.T) {
}
})
}
func TestResolveConfiguration(t *testing.T) {
t.Run("resolve atcConfig-yml", func(t *testing.T) {
expectedBodyString := "<?xml version=\"1.0\" encoding=\"UTF-8\"?><atc:runparameters xmlns:atc=\"http://www.sap.com/adt/atc\" xmlns:obj=\"http://www.sap.com/adt/objectset\" checkVariant=\"MY_TEST\" configuration=\"MY_CONFIG\"><obj:objectSet><obj:softwarecomponents><obj:softwarecomponent value=\"Z_TEST\"/><obj:softwarecomponent value=\"/DMO/SWC\"/></obj:softwarecomponents><obj:packages><obj:package value=\"Z_TEST\" includeSubpackages=\"false\"/></obj:packages></obj:objectSet></atc:runparameters>"
config := abapEnvironmentRunATCCheckOptions{
AtcConfig: "atc.yml",
}
dir, err := ioutil.TempDir("", "atcDir")
if err != nil {
t.Fatal("Failed to create temporary directory")
}
oldCWD, _ := os.Getwd()
_ = os.Chdir(dir)
// clean up tmp dir
defer func() {
_ = os.Chdir(oldCWD)
_ = os.RemoveAll(dir)
}()
yamlBody := `checkvariant: MY_TEST
configuration: MY_CONFIG
atcobjects:
package:
- name: Z_TEST
softwarecomponent:
- name: Z_TEST
- name: /DMO/SWC
`
err = ioutil.WriteFile(config.AtcConfig, []byte(yamlBody), 0644)
if assert.Equal(t, err, nil) {
bodyString, err := buildATCRequestBody(config)
assert.Equal(t, nil, err)
assert.Equal(t, expectedBodyString, bodyString)
}
})
t.Run("resolve repo-yml", func(t *testing.T) {
expectedBodyString := "<?xml version=\"1.0\" encoding=\"UTF-8\"?><atc:runparameters xmlns:atc=\"http://www.sap.com/adt/atc\" xmlns:obj=\"http://www.sap.com/adt/objectset\" checkVariant=\"ABAP_CLOUD_DEVELOPMENT_DEFAULT\"><obj:objectSet><obj:softwarecomponents><obj:softwarecomponent value=\"Z_TEST\"/><obj:softwarecomponent value=\"/DMO/SWC\"/></obj:softwarecomponents></obj:objectSet></atc:runparameters>"
config := abapEnvironmentRunATCCheckOptions{
Repositories: "repo.yml",
}
dir, err := ioutil.TempDir("", "test parse AUnit yaml config2")
if err != nil {
t.Fatal("Failed to create temporary directory")
}
oldCWD, _ := os.Getwd()
_ = os.Chdir(dir)
// clean up tmp dir
defer func() {
_ = os.Chdir(oldCWD)
_ = os.RemoveAll(dir)
}()
yamlBody := `repositories:
- name: Z_TEST
- name: /DMO/SWC
`
err = ioutil.WriteFile(config.Repositories, []byte(yamlBody), 0644)
if assert.Equal(t, err, nil) {
bodyString, err := buildATCRequestBody(config)
assert.Equal(t, nil, err)
assert.Equal(t, expectedBodyString, bodyString)
}
})
t.Run("Missing config files", func(t *testing.T) {
config := abapEnvironmentRunATCCheckOptions{
AtcConfig: "atc.yml",
}
bodyString, err := buildATCRequestBody(config)
assert.Equal(t, "Could not find atc.yml", err.Error())
assert.Equal(t, "", bodyString)
})
t.Run("Config file not specified", func(t *testing.T) {
config := abapEnvironmentRunATCCheckOptions{}
bodyString, err := buildATCRequestBody(config)
assert.Equal(t, "No configuration provided - please provide either an ATC configuration file or a repository configuration file", err.Error())
assert.Equal(t, "", bodyString)
})
}

View File

@@ -8,7 +8,6 @@ import (
"io/ioutil"
"net/http"
"net/http/cookiejar"
"path/filepath"
"reflect"
"strings"
"time"
@@ -19,7 +18,6 @@ import (
"github.com/SAP/jenkins-library/pkg/log"
"github.com/SAP/jenkins-library/pkg/piperutils"
"github.com/SAP/jenkins-library/pkg/telemetry"
"github.com/ghodss/yaml"
"github.com/pkg/errors"
)
@@ -96,7 +94,7 @@ func runAbapEnvironmentRunAUnitTest(config *abapEnvironmentRunAUnitTestOptions,
resp, err = triggerAUnitrun(*config, details, client)
}
if err == nil {
err = handleAUnitResults(resp, details, client, config.AUnitResultsFileName, config.GenerateHTML)
err = fetchAndPersistAUnitResults(resp, details, client, config.AUnitResultsFileName, config.GenerateHTML)
}
if err != nil {
log.Entry().WithError(err).Fatal("step execution failed")
@@ -106,40 +104,51 @@ func runAbapEnvironmentRunAUnitTest(config *abapEnvironmentRunAUnitTestOptions,
}
func triggerAUnitrun(config abapEnvironmentRunAUnitTestOptions, details abaputils.ConnectionDetailsHTTP, client piperhttp.Sender) (*http.Response, error) {
var aUnitConfigYamlFile []byte
abapEndpoint := details.URL
filelocation, err := filepath.Glob(config.AUnitConfig)
//Parse YAML AUnit run configuration as body for AUnit run trigger
if err == nil {
filename, err := filepath.Abs(filelocation[0])
if err == nil {
aUnitConfigYamlFile, err = ioutil.ReadFile(filename)
}
}
var AUnitConfig AUnitConfig
if err == nil {
var result []byte
result, err = yaml.YAMLToJSON(aUnitConfigYamlFile)
json.Unmarshal(result, &AUnitConfig)
}
var metadataString, optionsString, objectSetString string
if err == nil {
metadataString, optionsString, objectSetString, err = buildAUnitTestBody(AUnitConfig)
bodyString, err := buildAUnitRequestBody(config)
if err != nil {
return nil, err
}
//Trigger AUnit run
var resp *http.Response
var bodyString = `<?xml version="1.0" encoding="UTF-8"?>` + metadataString + optionsString + objectSetString
var body = []byte(bodyString)
if err == nil {
log.Entry().Debugf("Request Body: %s", bodyString)
details.URL = abapEndpoint + "/sap/bc/adt/api/abapunit/runs"
resp, err = runAUnit("POST", details, body, client)
log.Entry().Debugf("Request Body: %s", bodyString)
details.URL = abapEndpoint + "/sap/bc/adt/api/abapunit/runs"
resp, err = runAUnit("POST", details, body, client)
return resp, err
}
func resolveAUnitConfiguration(config abapEnvironmentRunAUnitTestOptions) (aUnitConfig AUnitConfig, err error) {
if config.AUnitConfig != "" {
// Configuration defaults to AUnitConfig
log.Entry().Infof("AUnit Configuration: %s", config.AUnitConfig)
result, err := abaputils.ReadConfigFile(config.AUnitConfig)
if err != nil {
return aUnitConfig, err
}
err = json.Unmarshal(result, &aUnitConfig)
return aUnitConfig, err
} else if config.Repositories != "" {
// Fallback / EasyMode is the Repositories configuration
log.Entry().Infof("AUnit Configuration derived from: %s", config.Repositories)
repos, err := abaputils.GetRepositories((&abaputils.RepositoriesConfig{Repositories: config.Repositories}))
if err != nil {
return aUnitConfig, err
}
for _, repo := range repos {
aUnitConfig.ObjectSet.SoftwareComponents = append(aUnitConfig.ObjectSet.SoftwareComponents, SoftwareComponents{Name: repo.Name})
}
aUnitConfig.Title = "AUnit Test Run"
return aUnitConfig, nil
} else {
// Fail if no configuration is provided
return aUnitConfig, errors.New("No configuration provided - please provide either an AUnit configuration file or a repository configuration file")
}
if err != nil {
return resp, fmt.Errorf("Triggering AUnit test run failed: %w", err)
}
return resp, nil
}
func convertAUnitOptions(options *abapEnvironmentRunAUnitTestOptions) abaputils.AbapEnvironmentOptions {
@@ -157,7 +166,7 @@ func convertAUnitOptions(options *abapEnvironmentRunAUnitTestOptions) abaputils.
return subOptions
}
func handleAUnitResults(resp *http.Response, details abaputils.ConnectionDetailsHTTP, client piperhttp.Sender, aunitResultFileName string, generateHTML bool) error {
func fetchAndPersistAUnitResults(resp *http.Response, details abaputils.ConnectionDetailsHTTP, client piperhttp.Sender, aunitResultFileName string, generateHTML bool) error {
var err error
var abapEndpoint string
abapEndpoint = details.URL
@@ -166,7 +175,7 @@ func handleAUnitResults(resp *http.Response, details abaputils.ConnectionDetails
location, err = pollAUnitRun(details, nil, client)
if err == nil {
details.URL = abapEndpoint + location
resp, err = getResultAUnitRun("GET", details, nil, client)
resp, err = getAUnitResults("GET", details, nil, client)
}
//Parse response
var body []byte
@@ -175,7 +184,7 @@ func handleAUnitResults(resp *http.Response, details abaputils.ConnectionDetails
}
if err == nil {
defer resp.Body.Close()
err = parseAUnitResult(body, aunitResultFileName, generateHTML)
err = persistAUnitResult(body, aunitResultFileName, generateHTML)
}
if err != nil {
return fmt.Errorf("Handling AUnit result failed: %w", err)
@@ -183,29 +192,35 @@ func handleAUnitResults(resp *http.Response, details abaputils.ConnectionDetails
return nil
}
func buildAUnitTestBody(AUnitConfig AUnitConfig) (metadataString string, optionsString string, objectSetString string, err error) {
func buildAUnitRequestBody(config abapEnvironmentRunAUnitTestOptions) (bodyString string, err error) {
bodyString = ""
AUnitConfig, err := resolveAUnitConfiguration(config)
if err != nil {
return bodyString, err
}
//Checks before building the XML body
if AUnitConfig.Title == "" {
return "", "", "", fmt.Errorf("Error while parsing AUnit test run config. No title for the AUnit run has been provided. Please configure an appropriate title for the respective test run")
return bodyString, fmt.Errorf("Error while parsing AUnit test run config. No title for the AUnit run has been provided. Please configure an appropriate title for the respective test run")
}
if AUnitConfig.Context == "" {
AUnitConfig.Context = "ABAP Environment Pipeline"
}
if reflect.DeepEqual(ObjectSet{}, AUnitConfig.ObjectSet) {
return "", "", "", fmt.Errorf("Error while parsing AUnit test run object set config. No object set has been provided. Please configure the objects you want to be checked for the respective test run")
return bodyString, fmt.Errorf("Error while parsing AUnit test run object set config. No object set has been provided. Please configure the objects you want to be checked for the respective test run")
}
//Build Options
optionsString += buildAUnitOptionsString(AUnitConfig)
optionsString := buildAUnitOptionsString(AUnitConfig)
//Build metadata string
metadataString += `<aunit:run title="` + AUnitConfig.Title + `" context="` + AUnitConfig.Context + `" xmlns:aunit="http://www.sap.com/adt/api/aunit">`
metadataString := `<aunit:run title="` + AUnitConfig.Title + `" context="` + AUnitConfig.Context + `" xmlns:aunit="http://www.sap.com/adt/api/aunit">`
//Build Object Set
objectSetString += buildAUnitObjectSetString(AUnitConfig)
objectSetString += `</aunit:run>`
objectSetString := buildAUnitObjectSetString(AUnitConfig)
return metadataString, optionsString, objectSetString, nil
bodyString += `<?xml version="1.0" encoding="UTF-8"?>` + metadataString + optionsString + objectSetString + `</aunit:run>`
return bodyString, nil
}
func runAUnit(requestType string, details abaputils.ConnectionDetailsHTTP, body []byte, client piperhttp.Sender) (*http.Response, error) {
@@ -282,11 +297,6 @@ func buildAUnitOptionsString(AUnitConfig AUnitConfig) (optionsString string) {
return optionsString
}
func buildOSLObjectSets(multipropertyset MultiPropertySet) (objectSetString string) {
objectSetString += writeObjectSetProperties(multipropertyset)
return objectSetString
}
func writeObjectSetProperties(set MultiPropertySet) (objectSetString string) {
for _, packages := range set.PackageNames {
objectSetString += `<osl:package name="` + packages.Name + `"/>`
@@ -342,10 +352,10 @@ func buildAUnitObjectSetString(AUnitConfig AUnitConfig) (objectSetString string)
PackageNames: s.PackageNames,
SoftwareComponents: s.SoftwareComponents,
}
objectSetString += buildOSLObjectSets(mps)
objectSetString += writeObjectSetProperties(mps)
}
objectSetString += buildOSLObjectSets(s.MultiPropertySet)
objectSetString += writeObjectSetProperties(s.MultiPropertySet)
if !(reflect.DeepEqual(s.MultiPropertySet, MultiPropertySet{})) {
log.Entry().Info("Wrong configuration has been detected: MultiPropertySet has been used. Please note that there is no official documentation for this usage. Please check the step documentation for more information")
@@ -422,7 +432,7 @@ func getHTTPResponseAUnitRun(requestType string, details abaputils.ConnectionDet
return req, err
}
func getResultAUnitRun(requestType string, details abaputils.ConnectionDetailsHTTP, body []byte, client piperhttp.Sender) (*http.Response, error) {
func getAUnitResults(requestType string, details abaputils.ConnectionDetailsHTTP, body []byte, client piperhttp.Sender) (*http.Response, error) {
log.Entry().WithField("ABAP Endpoint: ", details.URL).Info("Getting AUnit results")
@@ -437,7 +447,7 @@ func getResultAUnitRun(requestType string, details abaputils.ConnectionDetailsHT
return req, err
}
func parseAUnitResult(body []byte, aunitResultFileName string, generateHTML bool) (err error) {
func persistAUnitResult(body []byte, aunitResultFileName string, generateHTML bool) (err error) {
if len(body) == 0 {
return fmt.Errorf("Parsing AUnit result failed: %w", errors.New("Body is empty, can't parse empty body"))
}

View File

@@ -17,6 +17,7 @@ import (
type abapEnvironmentRunAUnitTestOptions struct {
AUnitConfig string `json:"aUnitConfig,omitempty"`
Repositories string `json:"repositories,omitempty"`
CfAPIEndpoint string `json:"cfApiEndpoint,omitempty"`
CfOrg string `json:"cfOrg,omitempty"`
CfServiceInstance string `json:"cfServiceInstance,omitempty"`
@@ -128,6 +129,7 @@ Regardless of the option you chose, please make sure to provide the object set c
func addAbapEnvironmentRunAUnitTestFlags(cmd *cobra.Command, stepConfig *abapEnvironmentRunAUnitTestOptions) {
cmd.Flags().StringVar(&stepConfig.AUnitConfig, "aUnitConfig", os.Getenv("PIPER_aUnitConfig"), "Path to a YAML configuration file for the object set to be checked during the AUnit test run")
cmd.Flags().StringVar(&stepConfig.Repositories, "repositories", os.Getenv("PIPER_repositories"), "Specifies a YAML file containing the repositories configuration")
cmd.Flags().StringVar(&stepConfig.CfAPIEndpoint, "cfApiEndpoint", os.Getenv("PIPER_cfApiEndpoint"), "Cloud Foundry API endpoint")
cmd.Flags().StringVar(&stepConfig.CfOrg, "cfOrg", os.Getenv("PIPER_cfOrg"), "Cloud Foundry org")
cmd.Flags().StringVar(&stepConfig.CfServiceInstance, "cfServiceInstance", os.Getenv("PIPER_cfServiceInstance"), "Parameter of ServiceInstance Name to delete Cloud Foundry Service")
@@ -139,7 +141,6 @@ func addAbapEnvironmentRunAUnitTestFlags(cmd *cobra.Command, stepConfig *abapEnv
cmd.Flags().StringVar(&stepConfig.AUnitResultsFileName, "aUnitResultsFileName", `AUnitResults.xml`, "Specifies output file name for the results from the AUnit run.")
cmd.Flags().BoolVar(&stepConfig.GenerateHTML, "generateHTML", false, "Specifies whether the AUnit results should also be generated as an HTML document")
cmd.MarkFlagRequired("aUnitConfig")
cmd.MarkFlagRequired("username")
cmd.MarkFlagRequired("password")
}
@@ -163,10 +164,19 @@ func abapEnvironmentRunAUnitTestMetadata() config.StepData {
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: true,
Mandatory: false,
Aliases: []config.Alias{},
Default: os.Getenv("PIPER_aUnitConfig"),
},
{
Name: "repositories",
ResourceRef: []config.ResourceReference{},
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
Default: os.Getenv("PIPER_repositories"),
},
{
Name: "cfApiEndpoint",
ResourceRef: []config.ResourceReference{},

View File

@@ -27,40 +27,29 @@ func newAbapEnvironmentRunAUnitTestTestsUtils() abapEnvironmentRunAUnitTestMockU
return utils
}
func TestBuildAUnitTestBody(t *testing.T) {
func TestBuildAUnitRequestBody(t *testing.T) {
t.Parallel()
t.Run("Test AUnit test run body with no data", func(t *testing.T) {
t.Parallel()
expectedmetadataString := ""
expectedoptionsString := ""
expectedobjectSetString := ""
var config abapEnvironmentRunAUnitTestOptions
var err error
var config AUnitConfig
var metadataString, optionsString, objectSetString string
bodyString, err := buildAUnitRequestBody(config)
expectedBodyString := ""
metadataString, optionsString, objectSetString, err = buildAUnitTestBody(config)
assert.Equal(t, expectedmetadataString, metadataString)
assert.Equal(t, expectedoptionsString, optionsString)
assert.Equal(t, expectedobjectSetString, objectSetString)
assert.EqualError(t, err, "Error while parsing AUnit test run config. No title for the AUnit run has been provided. Please configure an appropriate title for the respective test run")
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()
expectedmetadataString := `<aunit:run title="Test Title" context="Test Context" xmlns:aunit="http://www.sap.com/adt/api/aunit">`
expectedoptionsString := `<aunit:options><aunit:measurements type="none"/><aunit:scope ownTests="false" foreignTests="false"/><aunit:riskLevel harmless="false" dangerous="false" critical="false"/><aunit:duration short="false" medium="false" long="false"/></aunit:options>`
expectedobjectSetString := `</aunit:run>`
expectedobjectSetString := ``
var err error
var config AUnitConfig
config = AUnitConfig{
config := AUnitConfig{
Title: "Test Title",
Context: "Test Context",
Options: AUnitOptions{
@@ -110,27 +99,20 @@ func TestBuildAUnitTestBody(t *testing.T) {
},
}
var metadataString, optionsString, objectSetString string
objectSetString := buildAUnitObjectSetString(config)
optionsString := buildAUnitOptionsString(config)
metadataString, optionsString, objectSetString, err = buildAUnitTestBody(config)
assert.Equal(t, expectedmetadataString, metadataString)
assert.Equal(t, expectedoptionsString, optionsString)
assert.Equal(t, expectedobjectSetString, objectSetString)
assert.Equal(t, nil, err)
})
t.Run("Test AUnit test run body with example yaml config of only Multi Property Set", func(t *testing.T) {
t.Parallel()
expectedmetadataString := `<aunit:run title="Test Title" context="Test Context" xmlns:aunit="http://www.sap.com/adt/api/aunit">`
expectedoptionsString := `<aunit:options><aunit:measurements type="none"/><aunit:scope ownTests="false" foreignTests="false"/><aunit:riskLevel harmless="false" dangerous="false" critical="false"/><aunit:duration short="false" medium="false" long="false"/></aunit:options>`
expectedobjectSetString := `<osl:objectSet xsi:type="multiPropertySet" xmlns:osl="http://www.sap.com/api/osl" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><osl:softwareComponent name="testComponent1"/><osl:softwareComponent name="testComponent2"/></osl:objectSet></aunit:run>`
expectedobjectSetString := `<osl:objectSet xsi:type="multiPropertySet" xmlns:osl="http://www.sap.com/api/osl" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><osl:softwareComponent name="testComponent1"/><osl:softwareComponent name="testComponent2"/></osl:objectSet>`
var err error
var config AUnitConfig
config = AUnitConfig{
config := AUnitConfig{
Title: "Test Title",
Context: "Test Context",
Options: AUnitOptions{
@@ -165,27 +147,20 @@ func TestBuildAUnitTestBody(t *testing.T) {
},
}
var metadataString, optionsString, objectSetString string
objectSetString := buildAUnitObjectSetString(config)
optionsString := buildAUnitOptionsString(config)
metadataString, optionsString, objectSetString, err = buildAUnitTestBody(config)
assert.Equal(t, expectedmetadataString, metadataString)
assert.Equal(t, expectedoptionsString, optionsString)
assert.Equal(t, expectedobjectSetString, objectSetString)
assert.Equal(t, nil, err)
})
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()
expectedmetadataString := `<aunit:run title="Test Title" context="Test Context" xmlns:aunit="http://www.sap.com/adt/api/aunit">`
expectedoptionsString := `<aunit:options><aunit:measurements type="none"/><aunit:scope ownTests="false" foreignTests="false"/><aunit:riskLevel harmless="false" dangerous="false" critical="false"/><aunit:duration short="false" medium="false" long="false"/></aunit:options>`
expectedobjectSetString := `<osl:objectSet xsi:type="multiPropertySet" xmlns:osl="http://www.sap.com/api/osl" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><osl:softwareComponent name="testComponent1"/><osl:softwareComponent name="testComponent2"/></osl:objectSet></aunit:run>`
expectedobjectSetString := `<osl:objectSet xsi:type="multiPropertySet" xmlns:osl="http://www.sap.com/api/osl" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><osl:softwareComponent name="testComponent1"/><osl:softwareComponent name="testComponent2"/></osl:objectSet>`
var err error
var config AUnitConfig
config = AUnitConfig{
config := AUnitConfig{
Title: "Test Title",
Context: "Test Context",
Options: AUnitOptions{
@@ -220,27 +195,20 @@ func TestBuildAUnitTestBody(t *testing.T) {
},
}
var metadataString, optionsString, objectSetString string
objectSetString := buildAUnitObjectSetString(config)
optionsString := buildAUnitOptionsString(config)
metadataString, optionsString, objectSetString, err = buildAUnitTestBody(config)
assert.Equal(t, expectedmetadataString, metadataString)
assert.Equal(t, expectedoptionsString, optionsString)
assert.Equal(t, expectedobjectSetString, objectSetString)
assert.Equal(t, nil, err)
})
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()
expectedmetadataString := `<aunit:run title="Test Title" context="Test Context" xmlns:aunit="http://www.sap.com/adt/api/aunit">`
expectedoptionsString := `<aunit:options><aunit:measurements type="none"/><aunit:scope ownTests="false" foreignTests="false"/><aunit:riskLevel harmless="false" dangerous="false" critical="false"/><aunit:duration short="false" medium="false" long="false"/></aunit:options>`
expectedobjectSetString := `<osl:objectSet xsi:type="multiPropertySet" xmlns:osl="http://www.sap.com/api/osl" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><osl:package name="testPackage1"/><osl:package name="testPackage2"/><osl:softwareComponent name="testComponent1"/><osl:softwareComponent name="testComponent2"/></osl:objectSet></aunit:run>`
expectedobjectSetString := `<osl:objectSet xsi:type="multiPropertySet" xmlns:osl="http://www.sap.com/api/osl" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><osl:package name="testPackage1"/><osl:package name="testPackage2"/><osl:softwareComponent name="testComponent1"/><osl:softwareComponent name="testComponent2"/></osl:objectSet>`
var err error
var config AUnitConfig
config = AUnitConfig{
config := AUnitConfig{
Title: "Test Title",
Context: "Test Context",
Options: AUnitOptions{
@@ -274,79 +242,18 @@ func TestBuildAUnitTestBody(t *testing.T) {
},
}
var metadataString, optionsString, objectSetString string
objectSetString := buildAUnitObjectSetString(config)
optionsString := buildAUnitOptionsString(config)
metadataString, optionsString, objectSetString, err = buildAUnitTestBody(config)
assert.Equal(t, expectedmetadataString, metadataString)
assert.Equal(t, expectedoptionsString, optionsString)
assert.Equal(t, expectedobjectSetString, objectSetString)
assert.Equal(t, nil, err)
})
t.Run("Test AUnit test run body with example yaml config fail: no Title", func(t *testing.T) {
t.Parallel()
expectedmetadataString := ""
expectedoptionsString := ""
expectedobjectSetString := ""
var err error
var config AUnitConfig
config = AUnitConfig{}
var metadataString, optionsString, objectSetString string
metadataString, optionsString, objectSetString, err = buildAUnitTestBody(config)
assert.Equal(t, expectedmetadataString, metadataString)
assert.Equal(t, expectedoptionsString, optionsString)
assert.Equal(t, expectedobjectSetString, objectSetString)
assert.EqualError(t, err, "Error while parsing AUnit test run config. No title for the AUnit run has been provided. Please configure an appropriate title for the respective test run")
})
t.Run("Test AUnit test run body with example yaml config: no Context", func(t *testing.T) {
t.Parallel()
expectedmetadataString := `<aunit:run title="Test" context="ABAP Environment Pipeline" xmlns:aunit="http://www.sap.com/adt/api/aunit">`
expectedoptionsString := `<aunit:options><aunit:measurements type="none"/><aunit:scope ownTests="true" foreignTests="true"/><aunit:riskLevel harmless="true" dangerous="true" critical="true"/><aunit:duration short="true" medium="true" long="true"/></aunit:options>`
expectedobjectSetString := `<osl:objectSet xsi:type="multiPropertySet" xmlns:osl="http://www.sap.com/api/osl" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><osl:package name="testPackage1"/><osl:softwareComponent name="testComponent1"/></osl:objectSet></aunit:run>`
var err error
var config AUnitConfig
config = AUnitConfig{Title: "Test",
ObjectSet: ObjectSet{
PackageNames: []AUnitPackage{{
Name: "testPackage1",
}},
SoftwareComponents: []SoftwareComponents{{
Name: "testComponent1",
}},
}}
var metadataString, optionsString, objectSetString string
metadataString, optionsString, objectSetString, err = buildAUnitTestBody(config)
assert.Equal(t, expectedmetadataString, metadataString)
assert.Equal(t, expectedoptionsString, optionsString)
assert.Equal(t, expectedobjectSetString, objectSetString)
assert.Equal(t, err, nil)
})
t.Run("Test AUnit test run body with example yaml config: no Options", func(t *testing.T) {
t.Parallel()
expectedmetadataString := `<aunit:run title="Test" context="Test" xmlns:aunit="http://www.sap.com/adt/api/aunit">`
expectedoptionsString := `<aunit:options><aunit:measurements type="none"/><aunit:scope ownTests="true" foreignTests="true"/><aunit:riskLevel harmless="true" dangerous="true" critical="true"/><aunit:duration short="true" medium="true" long="true"/></aunit:options>`
expectedobjectSetString := `<osl:objectSet xsi:type="multiPropertySet" xmlns:osl="http://www.sap.com/api/osl" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><osl:package name="testPackage1"/><osl:softwareComponent name="testComponent1"/></osl:objectSet></aunit:run>`
var err error
var config AUnitConfig
config = AUnitConfig{Title: "Test", Context: "Test",
config := AUnitConfig{Title: "Test", Context: "Test",
ObjectSet: ObjectSet{
PackageNames: []AUnitPackage{{
Name: "testPackage1",
@@ -356,36 +263,134 @@ func TestBuildAUnitTestBody(t *testing.T) {
}},
}}
var metadataString, optionsString, objectSetString string
metadataString, optionsString, objectSetString, err = buildAUnitTestBody(config)
assert.Equal(t, expectedmetadataString, metadataString)
optionsString := buildAUnitOptionsString(config)
assert.Equal(t, expectedoptionsString, optionsString)
assert.Equal(t, expectedobjectSetString, objectSetString)
assert.Equal(t, err, nil)
})
t.Run("Test AUnit test run body with example yaml config fail: no ObjectSet", func(t *testing.T) {
t.Parallel()
t.Run("Config with repository-yml", func(t *testing.T) {
expectedmetadataString := ""
expectedoptionsString := ""
expectedobjectSetString := ""
config := abapEnvironmentRunAUnitTestOptions{
AUnitResultsFileName: "aUnitResults.xml",
Repositories: "repositories.yml",
}
var err error
var config AUnitConfig
dir, err := ioutil.TempDir("", "test parse AUnit yaml config2")
if err != nil {
t.Fatal("Failed to create temporary directory")
}
oldCWD, _ := os.Getwd()
_ = os.Chdir(dir)
// clean up tmp dir
defer func() {
_ = os.Chdir(oldCWD)
_ = os.RemoveAll(dir)
}()
config = AUnitConfig{Title: "Test", Context: "Test", Options: AUnitOptions{Measurements: "Test"}}
repositories := `repositories:
- name: /DMO/REPO
branch: main
`
expectedBodyString := "<?xml version=\"1.0\" encoding=\"UTF-8\"?><aunit:run title=\"AUnit Test Run\" context=\"ABAP Environment Pipeline\" xmlns:aunit=\"http://www.sap.com/adt/api/aunit\"><aunit:options><aunit:measurements type=\"none\"/><aunit:scope ownTests=\"true\" foreignTests=\"true\"/><aunit:riskLevel harmless=\"true\" dangerous=\"true\" critical=\"true\"/><aunit:duration short=\"true\" medium=\"true\" long=\"true\"/></aunit:options><osl:objectSet xsi:type=\"multiPropertySet\" xmlns:osl=\"http://www.sap.com/api/osl\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><osl:softwareComponent name=\"/DMO/REPO\"/></osl:objectSet></aunit:run>"
err = ioutil.WriteFile(config.Repositories, []byte(repositories), 0644)
if assert.Equal(t, err, nil) {
bodyString, err := buildAUnitRequestBody(config)
assert.Equal(t, nil, err)
assert.Equal(t, expectedBodyString, bodyString)
}
})
var metadataString, optionsString, objectSetString string
t.Run("Config with aunitconfig-yml", func(t *testing.T) {
metadataString, optionsString, objectSetString, err = buildAUnitTestBody(config)
config := abapEnvironmentRunAUnitTestOptions{
AUnitResultsFileName: "aUnitResults.xml",
AUnitConfig: "aunit.yml",
}
assert.Equal(t, expectedmetadataString, metadataString)
assert.Equal(t, expectedoptionsString, optionsString)
assert.Equal(t, expectedobjectSetString, objectSetString)
assert.EqualError(t, err, "Error while parsing AUnit test run object set config. No object set has been provided. Please configure the objects you want to be checked for the respective test run")
dir, err := ioutil.TempDir("", "test parse AUnit yaml config2")
if err != nil {
t.Fatal("Failed to create temporary directory")
}
oldCWD, _ := os.Getwd()
_ = os.Chdir(dir)
// clean up tmp dir
defer func() {
_ = os.Chdir(oldCWD)
_ = os.RemoveAll(dir)
}()
yamlBody := `title: My AUnit run
objectset:
packages:
- name: Z_TEST
softwarecomponents:
- name: Z_TEST
- name: /DMO/SWC
`
expectedBodyString := "<?xml version=\"1.0\" encoding=\"UTF-8\"?><aunit:run title=\"My AUnit run\" context=\"ABAP Environment Pipeline\" xmlns:aunit=\"http://www.sap.com/adt/api/aunit\"><aunit:options><aunit:measurements type=\"none\"/><aunit:scope ownTests=\"true\" foreignTests=\"true\"/><aunit:riskLevel harmless=\"true\" dangerous=\"true\" critical=\"true\"/><aunit:duration short=\"true\" medium=\"true\" long=\"true\"/></aunit:options><osl:objectSet xsi:type=\"multiPropertySet\" xmlns:osl=\"http://www.sap.com/api/osl\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><osl:package name=\"Z_TEST\"/><osl:softwareComponent name=\"Z_TEST\"/><osl:softwareComponent name=\"/DMO/SWC\"/></osl:objectSet></aunit:run>"
err = ioutil.WriteFile(config.AUnitConfig, []byte(yamlBody), 0644)
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, err := ioutil.TempDir("", "test parse AUnit yaml config2")
if err != nil {
t.Fatal("Failed to create temporary directory")
}
oldCWD, _ := os.Getwd()
_ = os.Chdir(dir)
// clean up tmp dir
defer func() {
_ = os.Chdir(oldCWD)
_ = os.RemoveAll(dir)
}()
yamlBody := `title: My AUnit run
objectset:
type: multiPropertySet
multipropertyset:
packages:
- name: Z_TEST
softwarecomponents:
- name: Z_TEST
- name: /DMO/SWC
`
expectedBodyString := "<?xml version=\"1.0\" encoding=\"UTF-8\"?><aunit:run title=\"My AUnit run\" context=\"ABAP Environment Pipeline\" xmlns:aunit=\"http://www.sap.com/adt/api/aunit\"><aunit:options><aunit:measurements type=\"none\"/><aunit:scope ownTests=\"true\" foreignTests=\"true\"/><aunit:riskLevel harmless=\"true\" dangerous=\"true\" critical=\"true\"/><aunit:duration short=\"true\" medium=\"true\" long=\"true\"/></aunit:options><osl:objectSet xsi:type=\"multiPropertySet\" xmlns:osl=\"http://www.sap.com/api/osl\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><osl:package name=\"Z_TEST\"/><osl:softwareComponent name=\"Z_TEST\"/><osl:softwareComponent name=\"/DMO/SWC\"/></osl:objectSet></aunit:run>"
err = ioutil.WriteFile(config.AUnitConfig, []byte(yamlBody), 0644)
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())
})
}
@@ -528,7 +533,7 @@ func TestParseAUnitResult(t *testing.T) {
}()
bodyString := `<?xml version="1.0" encoding="utf-8"?><testsuites title="My AUnit run" system="TST" client="100" executedBy="TESTUSER" time="000.000" timestamp="2021-01-01T00:00:00Z" failures="2" errors="2" skipped="0" asserts="0" tests="2"><testsuite name="" tests="2" failures="2" errors="0" skipped="0" asserts="0" package="testpackage" timestamp="2021-01-01T00:00:00ZZ" time="0.000" hostname="test"><testcase classname="test" name="execute" time="0.000" asserts="2"><failure message="testMessage1" type="Assert Failure">Test1</failure><failure message="testMessage2" type="Assert Failure">Test2</failure></testcase></testsuite></testsuites>`
body := []byte(bodyString)
err = parseAUnitResult(body, "AUnitResults.xml", false)
err = persistAUnitResult(body, "AUnitResults.xml", false)
assert.Equal(t, nil, err)
})
@@ -547,7 +552,7 @@ func TestParseAUnitResult(t *testing.T) {
}()
bodyString := `<?xml version="1.0" encoding="UTF-8"?>`
body := []byte(bodyString)
err = parseAUnitResult(body, "AUnitResults.xml", false)
err = persistAUnitResult(body, "AUnitResults.xml", false)
assert.Equal(t, nil, err)
})
@@ -556,7 +561,7 @@ func TestParseAUnitResult(t *testing.T) {
var bodyString string
body := []byte(bodyString)
err := parseAUnitResult(body, "AUnitResults.xml", false)
err := persistAUnitResult(body, "AUnitResults.xml", false)
assert.EqualError(t, err, "Parsing AUnit result failed: Body is empty, can't parse empty body")
})
}
@@ -576,7 +581,7 @@ func TestGetResultAUnitRun(t *testing.T) {
Password: "Test",
URL: "https://api.endpoint.com/Entity/",
}
resp, err := getResultAUnitRun("GET", con, []byte(client.Body), client)
resp, err := getAUnitResults("GET", con, []byte(client.Body), client)
defer resp.Body.Close()
if assert.Equal(t, nil, err) {
buf := new(bytes.Buffer)
@@ -603,7 +608,7 @@ func TestGetResultAUnitRun(t *testing.T) {
Password: "Test",
URL: "https://api.endpoint.com/Entity/",
}
resp, err := getResultAUnitRun("GET", con, []byte(client.Body), client)
resp, err := getAUnitResults("GET", con, []byte(client.Body), client)
defer resp.Body.Close()
if assert.EqualError(t, err, "Getting AUnit run results failed: Test fail") {
buf := new(bytes.Buffer)