You've already forked sap-jenkins-library
							
							
				mirror of
				https://github.com/SAP/jenkins-library.git
				synced 2025-10-30 23:57:50 +02:00 
			
		
		
		
	chore: cleanup reporting & some incorrect file usage in tests (#3943)
* chore: cleanup reporting & some incorrect file usage in tests * cleanup interface * chore: remove comment * preserve error handling * Rename FileUtils.go to fileUtils.go * clean up formatting * chore: address static check findings * fix brittle test * chore: cleanup formatting
This commit is contained in:
		| @@ -16,19 +16,19 @@ import ( | ||||
| func abapAddonAssemblyKitCheckPV(config abapAddonAssemblyKitCheckPVOptions, telemetryData *telemetry.CustomData, cpe *abapAddonAssemblyKitCheckPVCommonPipelineEnvironment) { | ||||
| 	utils := aakaas.NewAakBundle() | ||||
| 	// error situations should stop execution through log.Entry().Fatal() call which leads to an os.Exit(1) in the end | ||||
| 	if err := runAbapAddonAssemblyKitCheckPV(&config, telemetryData, &utils, cpe); err != nil { | ||||
| 	if err := runAbapAddonAssemblyKitCheckPV(&config, telemetryData, utils, cpe); err != nil { | ||||
| 		log.Entry().WithError(err).Fatal("step execution failed") | ||||
| 	} | ||||
| } | ||||
| func runAbapAddonAssemblyKitCheckPV(config *abapAddonAssemblyKitCheckPVOptions, telemetryData *telemetry.CustomData, utils *aakaas.AakUtils, cpe *abapAddonAssemblyKitCheckPVCommonPipelineEnvironment) error { | ||||
| func runAbapAddonAssemblyKitCheckPV(config *abapAddonAssemblyKitCheckPVOptions, telemetryData *telemetry.CustomData, utils aakaas.AakUtils, cpe *abapAddonAssemblyKitCheckPVCommonPipelineEnvironment) error { | ||||
|  | ||||
| 	conn := new(abapbuild.Connector) | ||||
| 	if err := conn.InitAAKaaS(config.AbapAddonAssemblyKitEndpoint, config.Username, config.Password, *utils); err != nil { | ||||
| 	if err := conn.InitAAKaaS(config.AbapAddonAssemblyKitEndpoint, config.Username, config.Password, utils); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	log.Entry().Infof("Reading Product Version Information from addonDescriptor (aka addon.yml) file: %s", config.AddonDescriptorFileName) | ||||
| 	addonDescriptor, err := (*utils).ReadAddonDescriptor(config.AddonDescriptorFileName) | ||||
| 	addonDescriptor, err := utils.ReadAddonDescriptor(config.AddonDescriptorFileName) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -57,8 +57,10 @@ func runAbapAddonAssemblyKitCheckPV(config *abapAddonAssemblyKitCheckPVOptions, | ||||
| 	var filesToPublish []piperutils.Path | ||||
| 	log.Entry().Infof("Add %s to be published", config.AddonDescriptorFileName) | ||||
| 	filesToPublish = append(filesToPublish, piperutils.Path{Target: config.AddonDescriptorFileName, Name: "AddonDescriptor", Mandatory: true}) | ||||
| 	log.Entry().Infof("Publsihing %v files", len(filesToPublish)) | ||||
| 	piperutils.PersistReportsAndLinks("abapAddonAssemblyKitCheckPV", "", filesToPublish, nil) | ||||
| 	log.Entry().Infof("Publishing %v files", len(filesToPublish)) | ||||
| 	if err := piperutils.PersistReportsAndLinks("abapAddonAssemblyKitCheckPV", "", utils, filesToPublish, nil); err != nil { | ||||
| 		log.Entry().WithError(err).Error("failed to persist report information") | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|   | ||||
| @@ -21,7 +21,7 @@ func TestCheckPVStep(t *testing.T) { | ||||
| 	config.Password = "dummyPassword" | ||||
| 	t.Run("step success", func(t *testing.T) { | ||||
| 		config.AddonDescriptorFileName = "success" | ||||
| 		err := runAbapAddonAssemblyKitCheckPV(&config, nil, &utils, &cpe) | ||||
| 		err := runAbapAddonAssemblyKitCheckPV(&config, nil, utils, &cpe) | ||||
| 		assert.NoError(t, err, "Did not expect error") | ||||
| 		var addonDescriptorFinal abaputils.AddonDescriptor | ||||
| 		err = json.Unmarshal([]byte(cpe.abap.addonDescriptor), &addonDescriptorFinal) | ||||
| @@ -32,7 +32,7 @@ func TestCheckPVStep(t *testing.T) { | ||||
| 	}) | ||||
| 	t.Run("step error - in ReadAddonDescriptor", func(t *testing.T) { | ||||
| 		config.AddonDescriptorFileName = "failing" | ||||
| 		err := runAbapAddonAssemblyKitCheckPV(&config, nil, &utils, &cpe) | ||||
| 		err := runAbapAddonAssemblyKitCheckPV(&config, nil, utils, &cpe) | ||||
| 		assert.Error(t, err, "Did expect error") | ||||
| 		assert.Equal(t, err.Error(), "error in ReadAddonDescriptor") | ||||
| 	}) | ||||
| @@ -40,7 +40,7 @@ func TestCheckPVStep(t *testing.T) { | ||||
| 		config.AddonDescriptorFileName = "success" | ||||
| 		bundle.SetBody("ErrorBody") | ||||
| 		bundle.SetError("error during validation") | ||||
| 		err := runAbapAddonAssemblyKitCheckPV(&config, nil, &utils, &cpe) | ||||
| 		err := runAbapAddonAssemblyKitCheckPV(&config, nil, utils, &cpe) | ||||
| 		assert.Error(t, err, "Did expect error") | ||||
| 	}) | ||||
| } | ||||
|   | ||||
| @@ -32,13 +32,14 @@ func abapEnvironmentAssemblePackages(config abapEnvironmentAssemblePackagesOptio | ||||
| 	} | ||||
|  | ||||
| 	client := piperhttp.Client{} | ||||
| 	err := runAbapEnvironmentAssemblePackages(&config, telemetryData, &autils, &client, cpe) | ||||
| 	utils := piperutils.Files{} | ||||
| 	err := runAbapEnvironmentAssemblePackages(&config, telemetryData, &autils, &utils, &client, cpe) | ||||
| 	if err != nil { | ||||
| 		log.Entry().WithError(err).Fatal("step execution failed") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func runAbapEnvironmentAssemblePackages(config *abapEnvironmentAssemblePackagesOptions, telemetryData *telemetry.CustomData, com abaputils.Communication, client abapbuild.HTTPSendLoader, cpe *abapEnvironmentAssemblePackagesCommonPipelineEnvironment) error { | ||||
| func runAbapEnvironmentAssemblePackages(config *abapEnvironmentAssemblePackagesOptions, telemetryData *telemetry.CustomData, com abaputils.Communication, utils piperutils.FileUtils, client abapbuild.HTTPSendLoader, cpe *abapEnvironmentAssemblePackagesCommonPipelineEnvironment) error { | ||||
| 	connBuild := new(abapbuild.Connector) | ||||
| 	if errConBuild := initAssemblePackagesConnection(connBuild, config, com, client); errConBuild != nil { | ||||
| 		return errConBuild | ||||
| @@ -71,7 +72,7 @@ func runAbapEnvironmentAssemblePackages(config *abapEnvironmentAssemblePackagesO | ||||
| 	} | ||||
|  | ||||
| 	log.Entry().Infof("Publishing %v files", len(filesToPublish)) | ||||
| 	piperutils.PersistReportsAndLinks("abapEnvironmentAssemblePackages", "", filesToPublish, nil) | ||||
| 	piperutils.PersistReportsAndLinks("abapEnvironmentAssemblePackages", "", utils, filesToPublish, nil) | ||||
|  | ||||
| 	var reposBackToCPE []abaputils.Repository | ||||
| 	for _, b := range builds { | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import ( | ||||
| 	abapbuild "github.com/SAP/jenkins-library/pkg/abap/build" | ||||
| 	"github.com/SAP/jenkins-library/pkg/abaputils" | ||||
| 	piperhttp "github.com/SAP/jenkins-library/pkg/http" | ||||
| 	"github.com/SAP/jenkins-library/pkg/mock" | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| ) | ||||
|  | ||||
| @@ -83,26 +84,24 @@ func TestStep(t *testing.T) { | ||||
| 	cpe := &abapEnvironmentAssemblePackagesCommonPipelineEnvironment{} | ||||
|  | ||||
| 	t.Run("abapEnvironmentAssemblePackages: nothing to do", func(t *testing.T) { | ||||
|  | ||||
| 		config := &abapEnvironmentAssemblePackagesOptions{ | ||||
| 			AddonDescriptor:             cpeAbapAddonDescriptorPackageLocked, | ||||
| 			MaxRuntimeInMinutes:         1, | ||||
| 			PollIntervalsInMilliseconds: 1, | ||||
| 		} | ||||
|  | ||||
| 		err := runAbapEnvironmentAssemblePackages(config, nil, autils, &client, cpe) | ||||
| 		err := runAbapEnvironmentAssemblePackages(config, nil, autils, &mock.FilesMock{}, &client, cpe) | ||||
| 		assert.NoError(t, err) | ||||
| 		assert.Contains(t, cpe.abap.addonDescriptor, `"InBuildScope":false`) | ||||
| 	}) | ||||
| 	t.Run("abapEnvironmentAssemblePackages: build", func(t *testing.T) { | ||||
|  | ||||
| 		config := &abapEnvironmentAssemblePackagesOptions{ | ||||
| 			AddonDescriptor:             cpeAbapAddonDescriptorPackageReserved, | ||||
| 			MaxRuntimeInMinutes:         1, | ||||
| 			PollIntervalsInMilliseconds: 1, | ||||
| 		} | ||||
|  | ||||
| 		err := runAbapEnvironmentAssemblePackages(config, nil, autils, &client, cpe) | ||||
| 		err := runAbapEnvironmentAssemblePackages(config, nil, autils, &mock.FilesMock{}, &client, cpe) | ||||
| 		assert.NoError(t, err) | ||||
| 		assert.Contains(t, cpe.abap.addonDescriptor, `SAPK-001AAINITAPC1.SAR`) | ||||
| 		assert.Contains(t, cpe.abap.addonDescriptor, `"InBuildScope":true`) | ||||
|   | ||||
| @@ -5,7 +5,6 @@ import ( | ||||
| 	"net/url" | ||||
| 	"reflect" | ||||
| 	"strings" | ||||
|  | ||||
| 	"time" | ||||
|  | ||||
| 	abapbuild "github.com/SAP/jenkins-library/pkg/abap/build" | ||||
| @@ -21,8 +20,8 @@ import ( | ||||
| type abapEnvironmentBuildUtils interface { | ||||
| 	command.ExecRunner | ||||
| 	abaputils.Communication | ||||
| 	abapbuild.Publish | ||||
| 	abapbuild.HTTPSendLoader | ||||
| 	piperutils.FileUtils | ||||
| 	getMaxRuntime() time.Duration | ||||
| 	getPollingInterval() time.Duration | ||||
| 	publish() | ||||
| @@ -32,6 +31,7 @@ type abapEnvironmentBuildUtilsBundle struct { | ||||
| 	*command.Command | ||||
| 	*piperhttp.Client | ||||
| 	*abaputils.AbapUtils | ||||
| 	*piperutils.Files | ||||
| 	maxRuntime      time.Duration | ||||
| 	pollingInterval time.Duration | ||||
| 	storePublish    publish | ||||
| @@ -44,14 +44,14 @@ type publish struct { | ||||
| 	links     []piperutils.Path | ||||
| } | ||||
|  | ||||
| func (p *publish) publish() { | ||||
| func (p *publish) publish(utils piperutils.FileUtils) { | ||||
| 	if p.stepName != "" { | ||||
| 		abapbuild.PersistReportsAndLinks(p.stepName, p.workspace, p.reports, p.links) | ||||
| 		piperutils.PersistReportsAndLinks(p.stepName, p.workspace, utils, p.reports, p.links) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (aEBUB *abapEnvironmentBuildUtilsBundle) publish() { | ||||
| 	aEBUB.storePublish.publish() | ||||
| 	aEBUB.storePublish.publish(aEBUB) | ||||
| } | ||||
|  | ||||
| func (aEBUB *abapEnvironmentBuildUtilsBundle) getMaxRuntime() time.Duration { | ||||
| @@ -63,7 +63,7 @@ func (aEBUB *abapEnvironmentBuildUtilsBundle) getPollingInterval() time.Duration | ||||
| } | ||||
|  | ||||
| func (aEBUB *abapEnvironmentBuildUtilsBundle) PersistReportsAndLinks(stepName, workspace string, reports, links []piperutils.Path) { | ||||
| 	//abapbuild.PersistReportsAndLinks(stepName, workspace, reports, links) | ||||
| 	// abapbuild.PersistReportsAndLinks(stepName, workspace, reports, links) | ||||
| 	if aEBUB.storePublish.stepName == "" { | ||||
| 		aEBUB.storePublish.stepName = stepName | ||||
| 		aEBUB.storePublish.workspace = workspace | ||||
| @@ -94,13 +94,12 @@ func newAbapEnvironmentBuildUtils(maxRuntime time.Duration, pollingInterval time | ||||
|  | ||||
| func abapEnvironmentBuild(config abapEnvironmentBuildOptions, telemetryData *telemetry.CustomData, cpe *abapEnvironmentBuildCommonPipelineEnvironment) { | ||||
| 	utils := newAbapEnvironmentBuildUtils(time.Duration(config.MaxRuntimeInMinutes), time.Duration(config.PollingIntervalInSeconds)) | ||||
| 	if err := runAbapEnvironmentBuild(&config, telemetryData, &utils, cpe); err != nil { | ||||
| 	if err := runAbapEnvironmentBuild(&config, telemetryData, utils, cpe); err != nil { | ||||
| 		log.Entry().WithError(err).Fatal("step execution failed") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func runAbapEnvironmentBuild(config *abapEnvironmentBuildOptions, telemetryData *telemetry.CustomData, utils *abapEnvironmentBuildUtils, cpe *abapEnvironmentBuildCommonPipelineEnvironment) error { | ||||
|  | ||||
| func runAbapEnvironmentBuild(config *abapEnvironmentBuildOptions, telemetryData *telemetry.CustomData, utils abapEnvironmentBuildUtils, cpe *abapEnvironmentBuildCommonPipelineEnvironment) error { | ||||
| 	conn := new(abapbuild.Connector) | ||||
| 	if err := initConnection(conn, config, utils); err != nil { | ||||
| 		return errors.Wrap(err, "Connector initialization for communication with the ABAP system failed") | ||||
| @@ -112,8 +111,8 @@ func runAbapEnvironmentBuild(config *abapEnvironmentBuildOptions, telemetryData | ||||
| 	} | ||||
|  | ||||
| 	finalValues, err := runBuilds(conn, config, utils, valuesList) | ||||
| 	//files should be published, even if an error occured | ||||
| 	(*utils).publish() | ||||
| 	// files should be published, even if an error occured | ||||
| 	utils.publish() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -125,9 +124,9 @@ func runAbapEnvironmentBuild(config *abapEnvironmentBuildOptions, telemetryData | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func runBuilds(conn *abapbuild.Connector, config *abapEnvironmentBuildOptions, utils *abapEnvironmentBuildUtils, valuesList [][]abapbuild.Value) ([]abapbuild.Value, error) { | ||||
| func runBuilds(conn *abapbuild.Connector, config *abapEnvironmentBuildOptions, utils abapEnvironmentBuildUtils, valuesList [][]abapbuild.Value) ([]abapbuild.Value, error) { | ||||
| 	var finalValues []abapbuild.Value | ||||
| 	//No addonDescriptor involved | ||||
| 	// No addonDescriptor involved | ||||
| 	if len(valuesList) == 0 { | ||||
| 		values, err := generateValuesOnlyFromConfig(config) | ||||
| 		if err != nil { | ||||
| @@ -138,7 +137,7 @@ func runBuilds(conn *abapbuild.Connector, config *abapEnvironmentBuildOptions, u | ||||
| 			return finalValues, errors.Wrap(err, "Error during execution of build framework") | ||||
| 		} | ||||
| 	} else { | ||||
| 		//Run several times for each repository in the addonDescriptor | ||||
| 		// Run several times for each repository in the addonDescriptor | ||||
| 		var errstrings []string | ||||
| 		vE := valuesEvaluator{} | ||||
| 		vE.m = make(map[string]string) | ||||
| @@ -156,7 +155,7 @@ func runBuilds(conn *abapbuild.Connector, config *abapEnvironmentBuildOptions, u | ||||
| 				errstrings = append(errstrings, err.Error()) | ||||
| 			} | ||||
| 			finalValuesForOneBuild = removeAddonDescriptorValues(finalValuesForOneBuild, values) | ||||
| 			//This means: probably values are duplicated, but the first one wins -> perhaps change this in the future if needed | ||||
| 			// This means: probably values are duplicated, but the first one wins -> perhaps change this in the future if needed | ||||
| 			if err := vE.appendValuesIfNotPresent(finalValuesForOneBuild, false); err != nil { | ||||
| 				errstrings = append(errstrings, err.Error()) | ||||
| 			} | ||||
| @@ -170,7 +169,7 @@ func runBuilds(conn *abapbuild.Connector, config *abapEnvironmentBuildOptions, u | ||||
| 	return finalValues, nil | ||||
| } | ||||
|  | ||||
| func initConnection(conn *abapbuild.Connector, config *abapEnvironmentBuildOptions, utils *abapEnvironmentBuildUtils) error { | ||||
| func initConnection(conn *abapbuild.Connector, config *abapEnvironmentBuildOptions, utils abapEnvironmentBuildUtils) error { | ||||
| 	var connConfig abapbuild.ConnectorConfiguration | ||||
| 	connConfig.CfAPIEndpoint = config.CfAPIEndpoint | ||||
| 	connConfig.CfOrg = config.CfOrg | ||||
| @@ -187,17 +186,17 @@ func initConnection(conn *abapbuild.Connector, config *abapEnvironmentBuildOptio | ||||
| 		connConfig.Parameters.Add("sap-client", config.AbapSourceClient) | ||||
| 	} | ||||
|  | ||||
| 	if err := conn.InitBuildFramework(connConfig, *utils, *utils); err != nil { | ||||
| 	if err := conn.InitBuildFramework(connConfig, utils, utils); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	conn.MaxRuntime = (*utils).getMaxRuntime() | ||||
| 	conn.PollingInterval = (*utils).getPollingInterval() | ||||
| 	conn.MaxRuntime = utils.getMaxRuntime() | ||||
| 	conn.PollingInterval = utils.getPollingInterval() | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // ***********************************Run Build*************************************************************** | ||||
| func runBuild(conn *abapbuild.Connector, config *abapEnvironmentBuildOptions, utils *abapEnvironmentBuildUtils, values []abapbuild.Value) ([]abapbuild.Value, error) { | ||||
| func runBuild(conn *abapbuild.Connector, config *abapEnvironmentBuildOptions, utils abapEnvironmentBuildUtils, values []abapbuild.Value) ([]abapbuild.Value, error) { | ||||
| 	var finalValues []abapbuild.Value | ||||
| 	var inputValues abapbuild.Values | ||||
| 	inputValues.Values = values | ||||
| @@ -272,11 +271,11 @@ func (b *myBuild) Download() error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (b *myBuild) Publish(utils *abapEnvironmentBuildUtils) error { | ||||
| func (b *myBuild) Publish(utils abapEnvironmentBuildUtils) error { | ||||
| 	if b.PublishAllDownloadedResultFiles { | ||||
| 		b.PublishAllDownloadedResults("abapEnvironmentBuild", *utils) | ||||
| 		b.PublishAllDownloadedResults("abapEnvironmentBuild", utils) | ||||
| 	} else { | ||||
| 		if err := b.PublishDownloadedResults("abapEnvironmentBuild", b.PublishResultFilenames, *utils); err != nil { | ||||
| 		if err := b.PublishDownloadedResults("abapEnvironmentBuild", b.PublishResultFilenames, utils); err != nil { | ||||
| 			return errors.Wrapf(err, "Error during the publish of the result files %s", b.PublishResultFilenames) | ||||
| 		} | ||||
| 	} | ||||
| @@ -330,15 +329,15 @@ func removeAddonDescriptorValues(finalValuesFromBuild []abapbuild.Value, valuesF | ||||
| func generateValuesWithAddonDescriptor(config *abapEnvironmentBuildOptions, repoValues []abapbuild.Value) ([]abapbuild.Value, error) { | ||||
| 	var values []abapbuild.Value | ||||
| 	vE := valuesEvaluator{} | ||||
| 	//values from config | ||||
| 	// values from config | ||||
| 	if err := vE.initialize(config.Values); err != nil { | ||||
| 		return values, err | ||||
| 	} | ||||
| 	//values from addondescriptor | ||||
| 	// values from addondescriptor | ||||
| 	if err := vE.appendValuesIfNotPresent(repoValues, true); err != nil { | ||||
| 		return values, err | ||||
| 	} | ||||
| 	//values from commonepipelineEnvironment | ||||
| 	// values from commonepipelineEnvironment | ||||
| 	if err := vE.appendStringValuesIfNotPresent(config.CpeValues, false); err != nil { | ||||
| 		return values, err | ||||
| 	} | ||||
|   | ||||
| @@ -15,6 +15,7 @@ import ( | ||||
| type abapEnvironmentBuildMockUtils struct { | ||||
| 	*mock.ExecMockRunner | ||||
| 	*abapbuild.MockClient | ||||
| 	*mock.FilesMock | ||||
| } | ||||
|  | ||||
| func newAbapEnvironmentBuildTestsUtils() abapEnvironmentBuildUtils { | ||||
| @@ -22,6 +23,7 @@ func newAbapEnvironmentBuildTestsUtils() abapEnvironmentBuildUtils { | ||||
| 	utils := abapEnvironmentBuildMockUtils{ | ||||
| 		ExecMockRunner: &mock.ExecMockRunner{}, | ||||
| 		MockClient:     &mC, | ||||
| 		FilesMock:      &mock.FilesMock{}, | ||||
| 	} | ||||
| 	return &utils | ||||
| } | ||||
| @@ -31,6 +33,7 @@ func newAbapEnvironmentBuildTestsUtilsWithClient() abapEnvironmentBuildUtils { | ||||
| 	utils := abapEnvironmentBuildMockUtils{ | ||||
| 		ExecMockRunner: &mock.ExecMockRunner{}, | ||||
| 		MockClient:     &mC, | ||||
| 		FilesMock:      &mock.FilesMock{}, | ||||
| 	} | ||||
| 	return &utils | ||||
| } | ||||
| @@ -70,7 +73,7 @@ func TestRunAbapEnvironmentBuild(t *testing.T) { | ||||
| 		config.PublishAllDownloadedResultFiles = true | ||||
| 		utils := newAbapEnvironmentBuildTestsUtils() | ||||
| 		// test | ||||
| 		err := runAbapEnvironmentBuild(&config, nil, &utils, &cpe) | ||||
| 		err := runAbapEnvironmentBuild(&config, nil, utils, &cpe) | ||||
| 		// assert | ||||
| 		finalValues := `[{"value_id":"PHASE","value":"AUNIT"},{"value_id":"PACKAGES","value":"/BUILD/AUNIT_DUMMY_TESTS"},{"value_id":"MyId1","value":"AunitValue1"},{"value_id":"MyId2","value":"AunitValue2"},{"value_id":"BUILD_FRAMEWORK_MODE","value":"P"}]` | ||||
| 		assert.NoError(t, err) | ||||
| @@ -87,7 +90,7 @@ func TestRunAbapEnvironmentBuild(t *testing.T) { | ||||
| 		config.AbapSourceClient = "001" | ||||
| 		utils := newAbapEnvironmentBuildTestsUtilsWithClient() | ||||
| 		// test | ||||
| 		err := runAbapEnvironmentBuild(&config, nil, &utils, &cpe) | ||||
| 		err := runAbapEnvironmentBuild(&config, nil, utils, &cpe) | ||||
| 		// assert | ||||
| 		finalValues := `[{"value_id":"PHASE","value":"AUNIT"},{"value_id":"SUN","value":"SUMMER"}]` | ||||
| 		assert.NoError(t, err) | ||||
| @@ -105,7 +108,7 @@ func TestRunAbapEnvironmentBuild(t *testing.T) { | ||||
| 		config.PublishResultFilenames = []string{"SAR_XML"} | ||||
| 		utils := newAbapEnvironmentBuildTestsUtils() | ||||
| 		// test | ||||
| 		err := runAbapEnvironmentBuild(&config, nil, &utils, &cpe) | ||||
| 		err := runAbapEnvironmentBuild(&config, nil, utils, &cpe) | ||||
| 		// assert | ||||
| 		assert.NoError(t, err) | ||||
| 	}) | ||||
| @@ -124,7 +127,7 @@ func TestRunAbapEnvironmentBuild(t *testing.T) { | ||||
| 		config.UseFieldsOfAddonDescriptor = `[{"use":"Name","renameTo":"MyId1"},{"use":"Status","renameTo":"MyId2"}]` | ||||
| 		utils := newAbapEnvironmentBuildTestsUtils() | ||||
| 		// test | ||||
| 		err := runAbapEnvironmentBuild(&config, nil, &utils, &cpe) | ||||
| 		err := runAbapEnvironmentBuild(&config, nil, utils, &cpe) | ||||
| 		// assert | ||||
| 		finalValues := `[{"value_id":"PACKAGES","value":"/BUILD/AUNIT_DUMMY_TESTS"},{"value_id":"BUILD_FRAMEWORK_MODE","value":"P"}]` | ||||
| 		err = json.Unmarshal([]byte(finalValues), &expectedValueList) | ||||
| @@ -146,7 +149,7 @@ func TestRunAbapEnvironmentBuild(t *testing.T) { | ||||
| 		config.PublishResultFilenames = []string{"SAR_XML"} | ||||
| 		utils := newAbapEnvironmentBuildTestsUtils() | ||||
| 		// test | ||||
| 		err := runAbapEnvironmentBuild(&config, nil, &utils, &cpe) | ||||
| 		err := runAbapEnvironmentBuild(&config, nil, utils, &cpe) | ||||
| 		// assert | ||||
| 		assert.Error(t, err) | ||||
| 	}) | ||||
| @@ -162,7 +165,7 @@ func TestRunAbapEnvironmentBuild(t *testing.T) { | ||||
| 		config.PublishAllDownloadedResultFiles = true | ||||
| 		utils := newAbapEnvironmentBuildTestsUtils() | ||||
| 		// test | ||||
| 		err := runAbapEnvironmentBuild(&config, nil, &utils, &cpe) | ||||
| 		err := runAbapEnvironmentBuild(&config, nil, utils, &cpe) | ||||
| 		// assert | ||||
| 		assert.Error(t, err) | ||||
| 	}) | ||||
|   | ||||
| @@ -2,8 +2,8 @@ package cmd | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"io/ioutil" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/SAP/jenkins-library/pkg/abaputils" | ||||
| @@ -53,7 +53,6 @@ func TestFetchXcsrfTokenFromHead(t *testing.T) { | ||||
| func TestCheckATCSystemConfigurationFile(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 	t.Run("Check ATC Configuration File - empty", func(t *testing.T) { | ||||
|  | ||||
| 		errExpected := "pushing ATC System Configuration failed. Reason: Configured Filelocation is empty (File: atcSystemConfig.json)" | ||||
| 		var parsedConfigurationJsonExpected parsedConfigJsonWithExpand | ||||
| 		var atcSystemConfiguartionJsonFileExpected []byte | ||||
| @@ -71,7 +70,6 @@ func TestHandleHttpResponse(t *testing.T) { | ||||
| 	t.Parallel() | ||||
|  | ||||
| 	t.Run("failiure case: HandleHttpResponse", func(t *testing.T) { | ||||
|  | ||||
| 		bodyText := ` | ||||
| --B772E21DAA42B9571C778276B829D6C20 | ||||
| Content-Type: multipart/mixed; boundary=B772E21DAA42B9571C778276B829D6C21 | ||||
| @@ -139,13 +137,12 @@ cache-control: no-cache, no-store, must-revalidate | ||||
| 		} | ||||
| 		resp.Header.Set("Content-type", "multipart/mixed") | ||||
| 		err = HandleHttpResponse(resp, err, "Unit Test", con) | ||||
| 		//inner error expected | ||||
| 		// inner error expected | ||||
| 		errExpected := "Outer Response Code: 200 - but at least one Inner response returned StatusCode 4* or 5*. Please check Log for details." | ||||
| 		assert.Equal(t, errExpected, err.Error()) | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("success case: HandleHttpResponse", func(t *testing.T) { | ||||
|  | ||||
| 		bodyText := ` | ||||
| --B772E21DAA42B9571C778276B829D6C20 | ||||
| Content-Type: multipart/mixed; boundary=B772E21DAA42B9571C778276B829D6C21 | ||||
| @@ -221,7 +218,6 @@ func TestBuildATCSystemConfigBatchRequest(t *testing.T) { | ||||
| 	t.Parallel() | ||||
|  | ||||
| 	t.Run("success case: BuildATCSystemConfigBatch - Config Base & 1 Priority", func(t *testing.T) { | ||||
|  | ||||
| 		batchATCSystemConfigFileExpected := ` | ||||
| --request-separator | ||||
| Content-Type: multipart/mixed;boundary=changeset | ||||
| @@ -250,7 +246,7 @@ Content-Type: application/json | ||||
|  | ||||
| --request-separator--` | ||||
|  | ||||
| 		//no Configuration name supplied | ||||
| 		// no Configuration name supplied | ||||
| 		atcSystemConfigFileString := `{ | ||||
| 			"conf_name": "UNITTEST_PIPERSTEP", | ||||
| 			"checkvariant": "SAP_CLOUD_PLATFORM_ATC_DEFAULT", | ||||
| @@ -280,11 +276,9 @@ Content-Type: application/json | ||||
| 			t.Fatal("Failed to Build ATC System Config Batch") | ||||
| 		} | ||||
| 		assert.Equal(t, batchATCSystemConfigFileExpected, batchATCSystemConfigFile) | ||||
|  | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("success case: BuildATCSystemConfigBatch - Config Base & 2 Priorities", func(t *testing.T) { | ||||
|  | ||||
| 		batchATCSystemConfigFileExpected := ` | ||||
| --request-separator | ||||
| Content-Type: multipart/mixed;boundary=changeset | ||||
| @@ -323,7 +317,7 @@ Content-Type: application/json | ||||
|  | ||||
| --request-separator--` | ||||
|  | ||||
| 		//no Configuration name supplied | ||||
| 		// no Configuration name supplied | ||||
| 		atcSystemConfigFileString := `{ | ||||
| 			"conf_name": "UNITTEST_PIPERSTEP", | ||||
| 			"checkvariant": "SAP_CLOUD_PLATFORM_ATC_DEFAULT", | ||||
| @@ -358,11 +352,9 @@ Content-Type: application/json | ||||
| 			t.Fatal("Failed to Build ATC System Config Batch Request") | ||||
| 		} | ||||
| 		assert.Equal(t, batchATCSystemConfigFileExpected, batchATCSystemConfigFile) | ||||
|  | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("success case: BuildATCSystemConfigBatch - Config Base only (no existing _priorities)", func(t *testing.T) { | ||||
|  | ||||
| 		batchATCSystemConfigFileExpected := ` | ||||
| --request-separator | ||||
| Content-Type: multipart/mixed;boundary=changeset | ||||
| @@ -381,7 +373,7 @@ Content-Type: application/json | ||||
|  | ||||
| --request-separator--` | ||||
|  | ||||
| 		//no Configuration name supplied | ||||
| 		// no Configuration name supplied | ||||
| 		atcSystemConfigFileString := `{ | ||||
| 			"conf_name": "UNITTEST_PIPERSTEP", | ||||
| 			"checkvariant": "SAP_CLOUD_PLATFORM_ATC_DEFAULT", | ||||
| @@ -403,11 +395,9 @@ Content-Type: application/json | ||||
| 			t.Fatal("Failed to Build ATC System Config Batch") | ||||
| 		} | ||||
| 		assert.Equal(t, batchATCSystemConfigFileExpected, batchATCSystemConfigFile) | ||||
|  | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("success case: BuildATCSystemConfigBatch - Config Base only (empty expand _priorities)", func(t *testing.T) { | ||||
|  | ||||
| 		batchATCSystemConfigFileExpected := ` | ||||
| --request-separator | ||||
| Content-Type: multipart/mixed;boundary=changeset | ||||
| @@ -426,7 +416,7 @@ Content-Type: application/json | ||||
|  | ||||
| --request-separator--` | ||||
|  | ||||
| 		//no Configuration name supplied | ||||
| 		// no Configuration name supplied | ||||
| 		atcSystemConfigFileString := `{ | ||||
| 			"conf_name": "UNITTEST_PIPERSTEP", | ||||
| 			"checkvariant": "SAP_CLOUD_PLATFORM_ATC_DEFAULT", | ||||
| @@ -450,14 +440,12 @@ Content-Type: application/json | ||||
| 			t.Fatal("Failed to Build ATC System Config Batch") | ||||
| 		} | ||||
| 		assert.Equal(t, batchATCSystemConfigFileExpected, batchATCSystemConfigFile) | ||||
|  | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("failure case: BuildATCSystemConfigBatch", func(t *testing.T) { | ||||
|  | ||||
| 		batchATCSystemConfigFileExpected := `` | ||||
|  | ||||
| 		//no Configuration name supplied | ||||
| 		// no Configuration name supplied | ||||
| 		atcSystemConfigFileString := `{ | ||||
| 			"conf_name": "UNITTEST_PIPERSTEP", | ||||
| 			"checkvariant": "SAP_CLOUD_PLATFORM_ATC_DEFAULT", | ||||
| @@ -487,14 +475,14 @@ Content-Type: application/json | ||||
| 			t.Fatal("Failed to Build ATC System Config Batch") | ||||
| 		} | ||||
| 		assert.NotEqual(t, batchATCSystemConfigFileExpected, batchATCSystemConfigFile) | ||||
|  | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func TestRunAbapEnvironmentPushATCSystemConfig(t *testing.T) { | ||||
| 	t.Parallel() | ||||
|  | ||||
| 	t.Run("run Step Failure - ATC System Configuration File empty", func(t *testing.T) { | ||||
| 		var autils = abaputils.AUtilsMock{} | ||||
| 		autils := abaputils.AUtilsMock{} | ||||
| 		defer autils.Cleanup() | ||||
| 		autils.ReturnedConnectionDetailsHTTP.Password = "password" | ||||
| 		autils.ReturnedConnectionDetailsHTTP.User = "user" | ||||
| @@ -511,19 +499,12 @@ func TestRunAbapEnvironmentPushATCSystemConfig(t *testing.T) { | ||||
| 		} | ||||
|  | ||||
| 		dir := t.TempDir() | ||||
| 		oldCWD, _ := os.Getwd() | ||||
| 		_ = os.Chdir(dir) | ||||
| 		// clean up tmp dir | ||||
|  | ||||
| 		defer func() { | ||||
| 			_ = os.Chdir(oldCWD) | ||||
| 		}() | ||||
|  | ||||
| 		config := abapEnvironmentPushATCSystemConfigOptions{AtcSystemConfigFilePath: "atcSystemConfig.json"} | ||||
| 		config := abapEnvironmentPushATCSystemConfigOptions{AtcSystemConfigFilePath: filepath.Join(dir, "atcSystemConfig.json")} | ||||
|  | ||||
| 		atcSystemConfigFileString := `` | ||||
|  | ||||
| 		err := ioutil.WriteFile(config.AtcSystemConfigFilePath, []byte(atcSystemConfigFileString), 0644) | ||||
| 		err := os.WriteFile(config.AtcSystemConfigFilePath, []byte(atcSystemConfigFileString), 0o644) | ||||
| 		if err != nil { | ||||
| 			t.Fatal("Failed to write File: " + config.AtcSystemConfigFilePath) | ||||
| 		} | ||||
| @@ -535,7 +516,7 @@ func TestRunAbapEnvironmentPushATCSystemConfig(t *testing.T) { | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("run Step Failure - ATC System Configuration invalid", func(t *testing.T) { | ||||
| 		var autils = abaputils.AUtilsMock{} | ||||
| 		autils := abaputils.AUtilsMock{} | ||||
| 		defer autils.Cleanup() | ||||
| 		autils.ReturnedConnectionDetailsHTTP.Password = "password" | ||||
| 		autils.ReturnedConnectionDetailsHTTP.User = "user" | ||||
| @@ -552,17 +533,10 @@ func TestRunAbapEnvironmentPushATCSystemConfig(t *testing.T) { | ||||
| 		} | ||||
|  | ||||
| 		dir := t.TempDir() | ||||
| 		oldCWD, _ := os.Getwd() | ||||
| 		_ = os.Chdir(dir) | ||||
| 		// clean up tmp dir | ||||
|  | ||||
| 		defer func() { | ||||
| 			_ = os.Chdir(oldCWD) | ||||
| 		}() | ||||
| 		config := abapEnvironmentPushATCSystemConfigOptions{AtcSystemConfigFilePath: filepath.Join(dir, "atcSystemConfig.json")} | ||||
|  | ||||
| 		config := abapEnvironmentPushATCSystemConfigOptions{AtcSystemConfigFilePath: "atcSystemConfig.json"} | ||||
|  | ||||
| 		//no Configuration name supplied | ||||
| 		// no Configuration name supplied | ||||
| 		atcSystemConfigFileString := `{ | ||||
| 			"conf_name": "", | ||||
| 			"checkvariant": "SAP_CLOUD_PLATFORM_ATC_DEFAULT", | ||||
| @@ -585,7 +559,7 @@ func TestRunAbapEnvironmentPushATCSystemConfig(t *testing.T) { | ||||
| 			] | ||||
| 		} | ||||
| 		` | ||||
| 		err := ioutil.WriteFile(config.AtcSystemConfigFilePath, []byte(atcSystemConfigFileString), 0644) | ||||
| 		err := os.WriteFile(config.AtcSystemConfigFilePath, []byte(atcSystemConfigFileString), 0o644) | ||||
| 		if err != nil { | ||||
| 			t.Fatal("Failed to write File: " + config.AtcSystemConfigFilePath) | ||||
| 		} | ||||
| @@ -597,7 +571,7 @@ func TestRunAbapEnvironmentPushATCSystemConfig(t *testing.T) { | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("run Step Successful - Push ATC System Configuration", func(t *testing.T) { | ||||
| 		var autils = abaputils.AUtilsMock{} | ||||
| 		autils := abaputils.AUtilsMock{} | ||||
| 		defer autils.Cleanup() | ||||
| 		autils.ReturnedConnectionDetailsHTTP.Password = "password" | ||||
| 		autils.ReturnedConnectionDetailsHTTP.User = "user" | ||||
| @@ -614,17 +588,10 @@ func TestRunAbapEnvironmentPushATCSystemConfig(t *testing.T) { | ||||
| 		} | ||||
|  | ||||
| 		dir := t.TempDir() | ||||
| 		oldCWD, _ := os.Getwd() | ||||
| 		_ = os.Chdir(dir) | ||||
| 		// clean up tmp dir | ||||
|  | ||||
| 		defer func() { | ||||
| 			_ = os.Chdir(oldCWD) | ||||
| 		}() | ||||
| 		config := abapEnvironmentPushATCSystemConfigOptions{AtcSystemConfigFilePath: filepath.Join(dir, "atcSystemConfig.json")} | ||||
|  | ||||
| 		config := abapEnvironmentPushATCSystemConfigOptions{AtcSystemConfigFilePath: "atcSystemConfig.json"} | ||||
|  | ||||
| 		//valid ATC System Configuration File | ||||
| 		// valid ATC System Configuration File | ||||
| 		atcSystemConfigFileString := `{ | ||||
| 			"conf_name": "UNITTEST_PIPERSTEP", | ||||
| 			"checkvariant": "SAP_CLOUD_PLATFORM_ATC_DEFAULT", | ||||
| @@ -647,7 +614,7 @@ func TestRunAbapEnvironmentPushATCSystemConfig(t *testing.T) { | ||||
| 			] | ||||
| 		} | ||||
| 		` | ||||
| 		err := ioutil.WriteFile(config.AtcSystemConfigFilePath, []byte(atcSystemConfigFileString), 0644) | ||||
| 		err := os.WriteFile(config.AtcSystemConfigFilePath, []byte(atcSystemConfigFileString), 0o644) | ||||
| 		if err != nil { | ||||
| 			t.Fatal("Failed to write File: " + config.AtcSystemConfigFilePath) | ||||
| 		} | ||||
| @@ -657,7 +624,7 @@ func TestRunAbapEnvironmentPushATCSystemConfig(t *testing.T) { | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("run Step Failure - ATC System Configuration File does not exist", func(t *testing.T) { | ||||
| 		var autils = abaputils.AUtilsMock{} | ||||
| 		autils := abaputils.AUtilsMock{} | ||||
| 		defer autils.Cleanup() | ||||
| 		autils.ReturnedConnectionDetailsHTTP.Password = "password" | ||||
| 		autils.ReturnedConnectionDetailsHTTP.User = "user" | ||||
|   | ||||
| @@ -36,6 +36,7 @@ func abapEnvironmentRunATCCheck(options abapEnvironmentRunATCCheckOptions, telem | ||||
| 	var err error | ||||
|  | ||||
| 	client := piperhttp.Client{} | ||||
| 	fileUtils := piperutils.Files{} | ||||
| 	cookieJar, _ := cookiejar.New(nil) | ||||
| 	clientOptions := piperhttp.ClientOptions{ | ||||
| 		CookieJar: cookieJar, | ||||
| @@ -62,7 +63,7 @@ func abapEnvironmentRunATCCheck(options abapEnvironmentRunATCCheckOptions, telem | ||||
| 		resp, err = triggerATCRun(options, details, &client) | ||||
| 	} | ||||
| 	if err == nil { | ||||
| 		err = fetchAndPersistATCResults(resp, details, &client, options.AtcResultsFileName, options.GenerateHTML) | ||||
| 		err = fetchAndPersistATCResults(resp, details, &client, &fileUtils, options.AtcResultsFileName, options.GenerateHTML) | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		log.Entry().WithError(err).Fatal("step execution failed") | ||||
| @@ -71,7 +72,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 fetchAndPersistATCResults(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, utils piperutils.FileUtils, atcResultFileName string, generateHTML bool) error { | ||||
| 	var err error | ||||
| 	abapEndpoint := details.URL | ||||
| 	location := resp.Header.Get("Location") | ||||
| @@ -88,7 +89,7 @@ func fetchAndPersistATCResults(resp *http.Response, details abaputils.Connection | ||||
| 	} | ||||
| 	if err == nil { | ||||
| 		defer resp.Body.Close() | ||||
| 		err = logAndPersistATCResult(body, atcResultFileName, generateHTML) | ||||
| 		err = logAndPersistATCResult(utils, body, atcResultFileName, generateHTML) | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("Handling ATC result failed: %w", err) | ||||
| @@ -202,7 +203,7 @@ func getATCObjectSet(ATCConfig ATCConfiguration) (objectSet string, err error) { | ||||
| 	return objectSet, nil | ||||
| } | ||||
|  | ||||
| func logAndPersistATCResult(body []byte, atcResultFileName string, generateHTML bool) error { | ||||
| func logAndPersistATCResult(utils piperutils.FileUtils, body []byte, atcResultFileName string, generateHTML bool) error { | ||||
| 	if len(body) == 0 { | ||||
| 		return fmt.Errorf("Parsing ATC result failed: %w", errors.New("Body is empty, can't parse empty body")) | ||||
| 	} | ||||
| @@ -241,7 +242,7 @@ func logAndPersistATCResult(body []byte, atcResultFileName string, generateHTML | ||||
| 				reports = append(reports, piperutils.Path{Target: atcResultFileName, Name: "ATC Results HTML file", Mandatory: true}) | ||||
| 			} | ||||
| 		} | ||||
| 		piperutils.PersistReportsAndLinks("abapEnvironmentRunATCCheck", "", reports, nil) | ||||
| 		piperutils.PersistReportsAndLinks("abapEnvironmentRunATCCheck", "", utils, reports, nil) | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("Writing results failed: %w", err) | ||||
|   | ||||
| @@ -23,7 +23,7 @@ func TestHostConfig(t *testing.T) { | ||||
| 		} | ||||
|  | ||||
| 		execRunner := &mock.ExecMockRunner{} | ||||
| 		var autils = abaputils.AbapUtils{ | ||||
| 		autils := abaputils.AbapUtils{ | ||||
| 			Exec: execRunner, | ||||
| 		} | ||||
| 		var con abaputils.ConnectionDetailsHTTP | ||||
| @@ -37,7 +37,7 @@ func TestHostConfig(t *testing.T) { | ||||
| 		} | ||||
| 	}) | ||||
| 	t.Run("No host/ServiceKey configuration", func(t *testing.T) { | ||||
| 		//Testing without CfOrg parameter | ||||
| 		// Testing without CfOrg parameter | ||||
| 		config := abaputils.AbapEnvironmentOptions{ | ||||
| 			CfAPIEndpoint:     "https://api.endpoint.com", | ||||
| 			CfSpace:           "testSpace", | ||||
| @@ -51,7 +51,7 @@ func TestHostConfig(t *testing.T) { | ||||
| 		} | ||||
|  | ||||
| 		execRunner := &mock.ExecMockRunner{} | ||||
| 		var autils = abaputils.AbapUtils{ | ||||
| 		autils := abaputils.AbapUtils{ | ||||
| 			Exec: execRunner, | ||||
| 		} | ||||
|  | ||||
| @@ -76,7 +76,7 @@ func TestHostConfig(t *testing.T) { | ||||
| 			AbapEnvOptions: config, | ||||
| 		} | ||||
| 		execRunner := &mock.ExecMockRunner{} | ||||
| 		var autils = abaputils.AbapUtils{ | ||||
| 		autils := abaputils.AbapUtils{ | ||||
| 			Exec: execRunner, | ||||
| 		} | ||||
| 		var con abaputils.ConnectionDetailsHTTP | ||||
| @@ -242,7 +242,7 @@ func TestParseATCResult(t *testing.T) { | ||||
| 			</file> | ||||
| 		</checkstyle>` | ||||
| 		body := []byte(bodyString) | ||||
| 		err := logAndPersistATCResult(body, "ATCResults.xml", false) | ||||
| 		err := logAndPersistATCResult(&mock.FilesMock{}, body, "ATCResults.xml", false) | ||||
| 		assert.Equal(t, nil, err) | ||||
| 	}) | ||||
| 	t.Run("succes case: test parsing empty XML result", func(t *testing.T) { | ||||
| @@ -257,14 +257,14 @@ func TestParseATCResult(t *testing.T) { | ||||
| 		<checkstyle> | ||||
| 		</checkstyle>` | ||||
| 		body := []byte(bodyString) | ||||
| 		err := logAndPersistATCResult(body, "ATCResults.xml", false) | ||||
| 		err := logAndPersistATCResult(&mock.FilesMock{}, 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 := logAndPersistATCResult(body, "ATCResults.xml", false) | ||||
| 		err := logAndPersistATCResult(&mock.FilesMock{}, 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) { | ||||
| @@ -277,7 +277,7 @@ func TestParseATCResult(t *testing.T) { | ||||
| 		}() | ||||
| 		bodyString := `<html><head><title>HTMLTestResponse</title</head></html>` | ||||
| 		body := []byte(bodyString) | ||||
| 		err := logAndPersistATCResult(body, "ATCResults.xml", false) | ||||
| 		err := logAndPersistATCResult(&mock.FilesMock{}, 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") | ||||
| 	}) | ||||
| } | ||||
| @@ -294,7 +294,6 @@ func TestBuildATCCheckBody(t *testing.T) { | ||||
| 		assert.Equal(t, nil, err) | ||||
| 	}) | ||||
| 	t.Run("success case: Test build body with example yaml config", func(t *testing.T) { | ||||
|  | ||||
| 		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 := ATCConfiguration{ | ||||
| @@ -319,7 +318,6 @@ func TestBuildATCCheckBody(t *testing.T) { | ||||
| 		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) { | ||||
|  | ||||
| 		expectedObjectSet := `<obj:objectSet><obj:packages><obj:package value="testPackage" includeSubpackages="true"/><obj:package value="testPackage2" includeSubpackages="false"/></obj:packages></obj:objectSet>` | ||||
|  | ||||
| 		var err error | ||||
| @@ -342,7 +340,6 @@ func TestBuildATCCheckBody(t *testing.T) { | ||||
| 		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) { | ||||
|  | ||||
| 		expectedObjectSet := `<obj:objectSet><obj:softwarecomponents><obj:softwarecomponent value="testSoftwareComponent"/><obj:softwarecomponent value="testSoftwareComponent2"/></obj:softwarecomponents></obj:objectSet>` | ||||
|  | ||||
| 		config := ATCConfiguration{ | ||||
| @@ -365,7 +362,7 @@ func TestBuildATCCheckBody(t *testing.T) { | ||||
| } | ||||
|  | ||||
| func TestGenerateHTMLDocument(t *testing.T) { | ||||
| 	//Failure case is not needed --> all failing cases would be depended on parsedXML *Result which is covered in TestParseATCResult | ||||
| 	// Failure case is not needed --> all failing cases would be depended on parsedXML *Result which is covered in TestParseATCResult | ||||
| 	t.Run("success case: html response", func(t *testing.T) { | ||||
| 		expectedResult := "<!DOCTYPE html><html lang=\"en\" xmlns=\"http://www.w3.org/1999/xhtml\"><head><title>ATC Results</title><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" /><style>table,th,td {border: 1px solid black;border-collapse:collapse;}th,td{padding: 5px;text-align:left;font-size:medium;}</style></head><body><h1 style=\"text-align:left;font-size:large\">ATC Results</h1><table style=\"width:100%\"><tr><th>Severity</th><th>File</th><th>Message</th><th>Line</th><th>Checked by</th></tr><tr style=\"background-color: rgba(227,85,0)\"><td>error</td><td>testFile2</td><td>testMessage</td><td style=\"text-align:center\">1</td><td>sourceTester</td></tr><tr style=\"background-color: rgba(255,175,0, 0.75)\"><td>warning</td><td>testFile</td><td>testMessage2</td><td style=\"text-align:center\">2</td><td>sourceTester</td></tr><tr style=\"background-color: rgba(255,175,0, 0.2)\"><td>info</td><td>testFile</td><td>testMessage1</td><td style=\"text-align:center\">1</td><td>sourceTester</td></tr></table></body></html>" | ||||
|  | ||||
| @@ -393,9 +390,7 @@ func TestGenerateHTMLDocument(t *testing.T) { | ||||
| } | ||||
|  | ||||
| func TestResolveConfiguration(t *testing.T) { | ||||
|  | ||||
| 	t.Run("resolve atcConfig-yml with ATC Set", 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:package value=\"Z_TEST_TREE\" includeSubpackages=\"true\"/></obj:packages></obj:objectSet></atc:runparameters>" | ||||
| 		config := abapEnvironmentRunATCCheckOptions{ | ||||
| 			AtcConfig: "atc.yml", | ||||
| @@ -421,17 +416,15 @@ atcobjects: | ||||
|     - name: /DMO/SWC | ||||
| ` | ||||
|  | ||||
| 		err := ioutil.WriteFile(config.AtcConfig, []byte(yamlBody), 0644) | ||||
| 		err := ioutil.WriteFile(config.AtcConfig, []byte(yamlBody), 0o644) | ||||
| 		if assert.Equal(t, err, nil) { | ||||
| 			bodyString, err := buildATCRequestBody(config) | ||||
| 			assert.Equal(t, nil, err) | ||||
| 			assert.Equal(t, expectedBodyString, bodyString) | ||||
| 		} | ||||
|  | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("resolve atcConfig-yml with OSL", func(t *testing.T) { | ||||
|  | ||||
| 		config := abapEnvironmentRunATCCheckOptions{ | ||||
| 			AtcConfig: "atc.yml", | ||||
| 		} | ||||
| @@ -459,7 +452,7 @@ objectset: | ||||
| ` | ||||
| 		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\"><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:package name=\"Z_TEST_TREE\" includeSubpackages=\"true\"/><osl:softwareComponent name=\"Z_TEST\"/><osl:softwareComponent name=\"/DMO/SWC\"/></osl:objectSet></atc:runparameters>" | ||||
|  | ||||
| 		err := ioutil.WriteFile(config.AtcConfig, []byte(yamlBody), 0644) | ||||
| 		err := ioutil.WriteFile(config.AtcConfig, []byte(yamlBody), 0o644) | ||||
| 		if assert.Equal(t, err, nil) { | ||||
| 			bodyString, err := buildATCRequestBody(config) | ||||
| 			assert.Equal(t, nil, err) | ||||
| @@ -468,7 +461,6 @@ objectset: | ||||
| 	}) | ||||
|  | ||||
| 	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", | ||||
| @@ -487,17 +479,15 @@ objectset: | ||||
|   - name: /DMO/SWC | ||||
| ` | ||||
|  | ||||
| 		err := ioutil.WriteFile(config.Repositories, []byte(yamlBody), 0644) | ||||
| 		err := ioutil.WriteFile(config.Repositories, []byte(yamlBody), 0o644) | ||||
| 		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", | ||||
| 		} | ||||
| @@ -505,16 +495,13 @@ objectset: | ||||
| 		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) | ||||
|  | ||||
| 	}) | ||||
| } | ||||
|   | ||||
| @@ -34,15 +34,16 @@ func abapEnvironmentRunAUnitTest(config abapEnvironmentRunAUnitTestOptions, tele | ||||
| 	} | ||||
|  | ||||
| 	client := piperhttp.Client{} | ||||
| 	utils := piperutils.Files{} | ||||
|  | ||||
| 	// error situations should stop execution through log.Entry().Fatal() call which leads to an os.Exit(1) in the end | ||||
| 	err := runAbapEnvironmentRunAUnitTest(&config, telemetryData, &autils, &client) | ||||
| 	err := runAbapEnvironmentRunAUnitTest(&config, telemetryData, &autils, &client, &utils) | ||||
| 	if err != nil { | ||||
| 		log.Entry().WithError(err).Fatal("step execution failed") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func runAbapEnvironmentRunAUnitTest(config *abapEnvironmentRunAUnitTestOptions, telemetryData *telemetry.CustomData, com abaputils.Communication, client piperhttp.Sender) error { | ||||
| func runAbapEnvironmentRunAUnitTest(config *abapEnvironmentRunAUnitTestOptions, telemetryData *telemetry.CustomData, com abaputils.Communication, client piperhttp.Sender, utils piperutils.FileUtils) error { | ||||
| 	var details abaputils.ConnectionDetailsHTTP | ||||
| 	subOptions := convertAUnitOptions(config) | ||||
| 	details, err := com.GetAbapCommunicationArrangementInfo(subOptions, "") | ||||
| @@ -62,7 +63,7 @@ func runAbapEnvironmentRunAUnitTest(config *abapEnvironmentRunAUnitTestOptions, | ||||
| 		resp, err = triggerAUnitrun(*config, details, client) | ||||
| 	} | ||||
| 	if err == nil { | ||||
| 		err = fetchAndPersistAUnitResults(resp, details, client, config.AUnitResultsFileName, config.GenerateHTML) | ||||
| 		err = fetchAndPersistAUnitResults(resp, details, client, utils, config.AUnitResultsFileName, config.GenerateHTML) | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		log.Entry().WithError(err).Fatal("step execution failed") | ||||
| @@ -134,7 +135,7 @@ func convertAUnitOptions(options *abapEnvironmentRunAUnitTestOptions) abaputils. | ||||
| 	return subOptions | ||||
| } | ||||
|  | ||||
| func fetchAndPersistAUnitResults(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, utils piperutils.FileUtils, aunitResultFileName string, generateHTML bool) error { | ||||
| 	var err error | ||||
| 	abapEndpoint := details.URL | ||||
| 	location := resp.Header.Get("Location") | ||||
| @@ -151,7 +152,7 @@ func fetchAndPersistAUnitResults(resp *http.Response, details abaputils.Connecti | ||||
| 	} | ||||
| 	if err == nil { | ||||
| 		defer resp.Body.Close() | ||||
| 		err = persistAUnitResult(body, aunitResultFileName, generateHTML) | ||||
| 		err = persistAUnitResult(utils, body, aunitResultFileName, generateHTML) | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("Handling AUnit result failed: %w", err) | ||||
| @@ -344,7 +345,7 @@ func getAUnitResults(requestType string, details abaputils.ConnectionDetailsHTTP | ||||
| 	return req, err | ||||
| } | ||||
|  | ||||
| func persistAUnitResult(body []byte, aunitResultFileName string, generateHTML bool) (err error) { | ||||
| func persistAUnitResult(utils piperutils.FileUtils, 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")) | ||||
| 	} | ||||
| @@ -396,7 +397,7 @@ func persistAUnitResult(body []byte, aunitResultFileName string, generateHTML bo | ||||
| 	} | ||||
| 	//Persist findings afterwards | ||||
| 	reports = append(reports, piperutils.Path{Target: aunitResultFileName, Name: "AUnit Results", Mandatory: true}) | ||||
| 	piperutils.PersistReportsAndLinks("abapEnvironmentRunAUnitTest", "", reports, nil) | ||||
| 	piperutils.PersistReportsAndLinks("abapEnvironmentRunAUnitTest", "", utils, reports, nil) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
|   | ||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -7,7 +7,6 @@ import ( | ||||
| 	"encoding/xml" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"io/ioutil" | ||||
| 	"math" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| @@ -36,6 +35,7 @@ type checkmarxExecuteScanUtils interface { | ||||
| 	Stat(name string) (os.FileInfo, error) | ||||
| 	Open(name string) (*os.File, error) | ||||
| 	WriteFile(filename string, data []byte, perm os.FileMode) error | ||||
| 	MkdirAll(path string, perm os.FileMode) error | ||||
| 	PathMatch(pattern, name string) (bool, error) | ||||
| 	GetWorkspace() string | ||||
| 	GetIssueService() *github.IssuesService | ||||
| @@ -57,7 +57,11 @@ func (c *checkmarxExecuteScanUtilsBundle) GetWorkspace() string { | ||||
| } | ||||
|  | ||||
| func (c *checkmarxExecuteScanUtilsBundle) WriteFile(filename string, data []byte, perm os.FileMode) error { | ||||
| 	return ioutil.WriteFile(filename, data, perm) | ||||
| 	return os.WriteFile(filename, data, perm) | ||||
| } | ||||
|  | ||||
| func (c *checkmarxExecuteScanUtilsBundle) MkdirAll(path string, perm os.FileMode) error { | ||||
| 	return os.MkdirAll(path, perm) | ||||
| } | ||||
|  | ||||
| func (c *checkmarxExecuteScanUtilsBundle) FileInfoHeader(fi os.FileInfo) (*zip.FileHeader, error) { | ||||
| @@ -367,7 +371,7 @@ func verifyCxProjectCompliance(ctx context.Context, config checkmarxExecuteScanO | ||||
| 	} | ||||
|  | ||||
| 	// create toolrecord | ||||
| 	toolRecordFileName, err := createToolRecordCx(utils.GetWorkspace(), config, results) | ||||
| 	toolRecordFileName, err := createToolRecordCx(utils, utils.GetWorkspace(), config, results) | ||||
| 	if err != nil { | ||||
| 		// do not fail until the framework is well established | ||||
| 		log.Entry().Warning("TR_CHECKMARX: Failed to create toolrecord file ...", err) | ||||
| @@ -417,7 +421,7 @@ func verifyCxProjectCompliance(ctx context.Context, config checkmarxExecuteScanO | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	piperutils.PersistReportsAndLinks("checkmarxExecuteScan", utils.GetWorkspace(), reports, links) | ||||
| 	piperutils.PersistReportsAndLinks("checkmarxExecuteScan", utils.GetWorkspace(), utils, reports, links) | ||||
| 	reportToInflux(results, influx) | ||||
|  | ||||
| 	if insecure { | ||||
| @@ -962,8 +966,8 @@ func isFileNotMatchingPattern(patterns []string, path string, info os.FileInfo, | ||||
| 	return true, nil | ||||
| } | ||||
|  | ||||
| func createToolRecordCx(workspace string, config checkmarxExecuteScanOptions, results map[string]interface{}) (string, error) { | ||||
| 	record := toolrecord.New(workspace, "checkmarx", config.ServerURL) | ||||
| func createToolRecordCx(utils checkmarxExecuteScanUtils, workspace string, config checkmarxExecuteScanOptions, results map[string]interface{}) (string, error) { | ||||
| 	record := toolrecord.New(utils, workspace, "checkmarx", config.ServerURL) | ||||
| 	// Todo TeamId - see run_scan() | ||||
| 	// record.AddKeyData("team", XXX, resultMap["Team"], "") | ||||
| 	// Project | ||||
|   | ||||
| @@ -321,6 +321,10 @@ func (c *checkmarxExecuteScanUtilsMock) WriteFile(filename string, data []byte, | ||||
| 	return ioutil.WriteFile(filename, data, perm) | ||||
| } | ||||
|  | ||||
| func (c *checkmarxExecuteScanUtilsMock) MkdirAll(path string, perm os.FileMode) error { | ||||
| 	return os.MkdirAll(path, perm) | ||||
| } | ||||
|  | ||||
| func (c *checkmarxExecuteScanUtilsMock) FileInfoHeader(fi os.FileInfo) (*zip.FileHeader, error) { | ||||
| 	if c.errorOnFileInfoHeader { | ||||
| 		return nil, fmt.Errorf("error on FileInfoHeader") | ||||
|   | ||||
| @@ -16,7 +16,7 @@ import ( | ||||
| type codeqlExecuteScanUtils interface { | ||||
| 	command.ExecRunner | ||||
|  | ||||
| 	FileExists(filename string) (bool, error) | ||||
| 	piperutils.FileUtils | ||||
| } | ||||
|  | ||||
| type RepoInfo struct { | ||||
| @@ -226,7 +226,7 @@ func runCodeqlExecuteScan(config *codeqlExecuteScanOptions, telemetryData *telem | ||||
|  | ||||
| 	reports = append(reports, piperutils.Path{Target: fmt.Sprintf("%vtarget/codeqlReport.csv", config.ModulePath)}) | ||||
|  | ||||
| 	piperutils.PersistReportsAndLinks("codeqlExecuteScan", "./", reports, nil) | ||||
| 	piperutils.PersistReportsAndLinks("codeqlExecuteScan", "./", utils, reports, nil) | ||||
|  | ||||
| 	err = uploadResults(config, utils) | ||||
| 	if err != nil { | ||||
|   | ||||
| @@ -198,7 +198,7 @@ func runDetect(ctx context.Context, config detectExecuteScanOptions, utils detec | ||||
| 		} | ||||
| 	} | ||||
| 	// create Toolrecord file | ||||
| 	toolRecordFileName, toolRecordErr := createToolRecordDetect("./", config, blackduckSystem) | ||||
| 	toolRecordFileName, toolRecordErr := createToolRecordDetect(utils, "./", config, blackduckSystem) | ||||
| 	if toolRecordErr != nil { | ||||
| 		// do not fail until the framework is well established | ||||
| 		log.Entry().Warning("TR_DETECT: Failed to create toolrecord file "+toolRecordFileName, err) | ||||
| @@ -538,7 +538,7 @@ func postScanChecksAndReporting(ctx context.Context, config detectExecuteScanOpt | ||||
| 	} | ||||
| 	paths = append(paths, policyReportPaths...) | ||||
|  | ||||
| 	piperutils.PersistReportsAndLinks("detectExecuteScan", "", paths, nil) | ||||
| 	piperutils.PersistReportsAndLinks("detectExecuteScan", "", utils, paths, nil) | ||||
| 	if err != nil { | ||||
| 		errorsOccured = append(errorsOccured, fmt.Sprint(err)) | ||||
| 	} | ||||
| @@ -719,8 +719,8 @@ func isActivePolicyViolation(status string) bool { | ||||
| } | ||||
|  | ||||
| // create toolrecord file for detectExecute | ||||
| func createToolRecordDetect(workspace string, config detectExecuteScanOptions, sys *blackduckSystem) (string, error) { | ||||
| 	record := toolrecord.New(workspace, "detectExecute", config.ServerURL) | ||||
| func createToolRecordDetect(utils detectUtils, workspace string, config detectExecuteScanOptions, sys *blackduckSystem) (string, error) { | ||||
| 	record := toolrecord.New(utils, workspace, "detectExecute", config.ServerURL) | ||||
| 	project, err := sys.Client.GetProject(config.ProjectName) | ||||
| 	if err != nil { | ||||
| 		return "", fmt.Errorf("TR_DETECT: GetProject failed %v", err) | ||||
|   | ||||
| @@ -57,6 +57,7 @@ type pullRequestService interface { | ||||
| type fortifyUtils interface { | ||||
| 	maven.Utils | ||||
| 	gradle.Utils | ||||
| 	piperutils.FileUtils | ||||
|  | ||||
| 	SetDir(d string) | ||||
| 	GetArtifact(buildTool, buildDescriptorFile string, options *versioning.Options) (versioning.Artifact, error) | ||||
| @@ -122,7 +123,7 @@ func fortifyExecuteScan(config fortifyExecuteScanOptions, telemetryData *telemet | ||||
|  | ||||
| 	influx.step_data.fields.fortify = false | ||||
| 	reports, err := runFortifyScan(ctx, config, sys, utils, telemetryData, influx, auditStatus) | ||||
| 	piperutils.PersistReportsAndLinks("fortifyExecuteScan", config.ModulePath, reports, nil) | ||||
| 	piperutils.PersistReportsAndLinks("fortifyExecuteScan", config.ModulePath, utils, reports, nil) | ||||
| 	if err != nil { | ||||
| 		log.Entry().WithError(err).Fatal("Fortify scan and check failed") | ||||
| 	} | ||||
| @@ -229,7 +230,7 @@ func runFortifyScan(ctx context.Context, config fortifyExecuteScanOptions, sys f | ||||
|  | ||||
| 	// create toolrecord file | ||||
| 	// tbd - how to handle verifyOnly | ||||
| 	toolRecordFileName, err := createToolRecordFortify("./", config, project.ID, fortifyProjectName, projectVersion.ID, fortifyProjectVersion) | ||||
| 	toolRecordFileName, err := createToolRecordFortify(utils, "./", config, project.ID, fortifyProjectName, projectVersion.ID, fortifyProjectVersion) | ||||
| 	if err != nil { | ||||
| 		// do not fail until the framework is well established | ||||
| 		log.Entry().Warning("TR_FORTIFY: Failed to create toolrecord file ...", err) | ||||
| @@ -1211,8 +1212,8 @@ func getSeparator() string { | ||||
| 	return ":" | ||||
| } | ||||
|  | ||||
| func createToolRecordFortify(workspace string, config fortifyExecuteScanOptions, projectID int64, projectName string, projectVersionID int64, projectVersion string) (string, error) { | ||||
| 	record := toolrecord.New(workspace, "fortify", config.ServerURL) | ||||
| func createToolRecordFortify(utils fortifyUtils, workspace string, config fortifyExecuteScanOptions, projectID int64, projectName string, projectVersionID int64, projectVersion string) (string, error) { | ||||
| 	record := toolrecord.New(utils, workspace, "fortify", config.ServerURL) | ||||
| 	// Project | ||||
| 	err := record.AddKeyData("project", | ||||
| 		strconv.FormatInt(projectID, 10), | ||||
|   | ||||
| @@ -784,7 +784,7 @@ func (f filesMock) TempDir(dir string, pattern string) (name string, err error) | ||||
| 	if f.failOnCreation { | ||||
| 		return "", errors.New("error appeared") | ||||
| 	} | ||||
| 	return piperutils.Files{}.TempDir(dir, pattern) | ||||
| 	return piperutils.Files{}.TempDir("", pattern) | ||||
| } | ||||
|  | ||||
| func (f *filesMock) RemoveAll(path string) error { | ||||
|   | ||||
| @@ -22,6 +22,7 @@ const hadolintCommand = "hadolint" | ||||
| type HadolintPiperFileUtils interface { | ||||
| 	FileExists(filename string) (bool, error) | ||||
| 	FileWrite(filename string, data []byte, perm os.FileMode) error | ||||
| 	WriteFile(filename string, data []byte, perm os.FileMode) error | ||||
| } | ||||
|  | ||||
| // HadolintClient abstracts http.Client | ||||
| @@ -114,7 +115,7 @@ func runHadolint(config hadolintExecuteOptions, utils hadolintUtils) error { | ||||
| 	} | ||||
| 	//TODO: mock away in tests | ||||
| 	// persist report information | ||||
| 	piperutils.PersistReportsAndLinks("hadolintExecute", "./", []piperutils.Path{{Target: config.ReportFile}}, []piperutils.Path{}) | ||||
| 	piperutils.PersistReportsAndLinks("hadolintExecute", "./", utils, []piperutils.Path{{Target: config.ReportFile}}, []piperutils.Path{}) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -21,7 +21,9 @@ func TestRunHadolintExecute(t *testing.T) { | ||||
| 		} | ||||
|  | ||||
| 		fileMock. | ||||
| 			On("FileExists", config.ConfigurationFile).Return(false, nil) | ||||
| 			On("FileExists", config.ConfigurationFile).Return(false, nil). | ||||
| 			On("WriteFile", "hadolintExecute_reports.json", mock.Anything, mock.Anything).Return(nil). | ||||
| 			On("WriteFile", "hadolintExecute_links.json", mock.Anything, mock.Anything).Return(nil) | ||||
|  | ||||
| 		// test | ||||
| 		err := runHadolint(config, hadolintUtils{ | ||||
| @@ -62,7 +64,11 @@ func TestRunHadolintExecute(t *testing.T) { | ||||
| 			// checks if config exists before downloading | ||||
| 			On("FileExists", config.ConfigurationFile).Return(false, nil).Once(). | ||||
| 			// checks again but config is now downloaded | ||||
| 			On("FileExists", config.ConfigurationFile).Return(true, nil) | ||||
| 			On("FileExists", config.ConfigurationFile).Return(true, nil). | ||||
| 			On("WriteFile", "hadolintExecute_reports.json", mock.Anything, mock.Anything).Return(nil). | ||||
| 			On("WriteFile", "hadolintExecute_links.json", mock.Anything, mock.Anything).Return(nil) | ||||
|  | ||||
| 		//m.On("Do", MatchedBy(func(req *http.Request) bool { return req.Host == "example.com" })) | ||||
| 		// test | ||||
| 		err := runHadolint(config, hadolintUtils{ | ||||
| 			HadolintPiperFileUtils: fileMock, | ||||
|   | ||||
| @@ -98,7 +98,7 @@ func runMalwareScan(config *malwareExecuteScanOptions, telemetryData *telemetry. | ||||
| 	log.Entry().Infof("* Signatures: %s", scannerInfo.SignatureTimestamp) | ||||
| 	log.Entry().Infof("***************************************") | ||||
|  | ||||
| 	if _, err = createToolRecordMalwareScan("./", config, scannerInfo); err != nil { | ||||
| 	if _, err = createToolRecordMalwareScan(utils, "./", config, scannerInfo); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| @@ -187,8 +187,8 @@ func validateHash(remoteHash, fileName string, utils malwareScanUtils) error { | ||||
| } | ||||
|  | ||||
| // create toolrecord file for malwarescan | ||||
| func createToolRecordMalwareScan(workspace string, config *malwareExecuteScanOptions, scanner *malwarescan.Info) (string, error) { | ||||
| 	record := toolrecord.New(workspace, "malwarescan", config.Host) | ||||
| func createToolRecordMalwareScan(utils malwareScanUtils, workspace string, config *malwareExecuteScanOptions, scanner *malwarescan.Info) (string, error) { | ||||
| 	record := toolrecord.New(utils, workspace, "malwarescan", config.Host) | ||||
| 	record.SetOverallDisplayData("Malware Scanner", "") | ||||
|  | ||||
| 	if err := record.AddKeyData("engineVersion", scanner.EngineVersion, "Engine Version", ""); err != nil { | ||||
|   | ||||
| @@ -268,7 +268,7 @@ func executeProtecodeScan(influx *protecodeExecuteScanInflux, client protecode.P | ||||
| 	} | ||||
|  | ||||
| 	// create toolrecord file | ||||
| 	toolRecordFileName, err := createToolRecordProtecode("./", config, productID, webuiURL) | ||||
| 	toolRecordFileName, err := createToolRecordProtecode(utils, "./", config, productID, webuiURL) | ||||
| 	if err != nil { | ||||
| 		// do not fail until the framework is well established | ||||
| 		log.Entry().Warning("TR_PROTECODE: Failed to create toolrecord file ...", err) | ||||
| @@ -276,7 +276,7 @@ func executeProtecodeScan(influx *protecodeExecuteScanInflux, client protecode.P | ||||
| 		reports = append(reports, piperutils.Path{Target: toolRecordFileName}) | ||||
| 	} | ||||
|  | ||||
| 	piperutils.PersistReportsAndLinks("protecodeExecuteScan", "", reports, links) | ||||
| 	piperutils.PersistReportsAndLinks("protecodeExecuteScan", "", utils, reports, links) | ||||
|  | ||||
| 	if config.FailOnSevereVulnerabilities && protecode.HasSevereVulnerabilities(result.Result, config.ExcludeCVEs) { | ||||
| 		log.SetErrorCategory(log.ErrorCompliance) | ||||
| @@ -418,8 +418,8 @@ func getProcessedVersion(config *protecodeExecuteScanOptions) string { | ||||
|  | ||||
| // create toolrecord file for protecode | ||||
| // todo: check if group and product names can be retrieved | ||||
| func createToolRecordProtecode(workspace string, config *protecodeExecuteScanOptions, productID int, webuiURL string) (string, error) { | ||||
| 	record := toolrecord.New(workspace, "protecode", config.ServerURL) | ||||
| func createToolRecordProtecode(utils protecodeUtils, workspace string, config *protecodeExecuteScanOptions, productID int, webuiURL string) (string, error) { | ||||
| 	record := toolrecord.New(utils, workspace, "protecode", config.ServerURL) | ||||
| 	groupURL := config.ServerURL + "/#/groups/" + config.Group | ||||
| 	err := record.AddKeyData("group", | ||||
| 		config.Group, | ||||
|   | ||||
| @@ -18,9 +18,7 @@ import ( | ||||
| 	keytool "github.com/SAP/jenkins-library/pkg/java" | ||||
| 	"github.com/SAP/jenkins-library/pkg/log" | ||||
| 	"github.com/SAP/jenkins-library/pkg/orchestrator" | ||||
| 	FileUtils "github.com/SAP/jenkins-library/pkg/piperutils" | ||||
| 	SliceUtils "github.com/SAP/jenkins-library/pkg/piperutils" | ||||
| 	StepResults "github.com/SAP/jenkins-library/pkg/piperutils" | ||||
| 	"github.com/SAP/jenkins-library/pkg/piperutils" | ||||
| 	SonarUtils "github.com/SAP/jenkins-library/pkg/sonar" | ||||
| 	"github.com/SAP/jenkins-library/pkg/telemetry" | ||||
| 	"github.com/SAP/jenkins-library/pkg/versioning" | ||||
| @@ -45,8 +43,8 @@ var ( | ||||
| 	sonar sonarSettings | ||||
|  | ||||
| 	execLookPath    = exec.LookPath | ||||
| 	fileUtilsExists = FileUtils.FileExists | ||||
| 	fileUtilsUnzip  = FileUtils.Unzip | ||||
| 	fileUtilsExists = piperutils.FileExists | ||||
| 	fileUtilsUnzip  = piperutils.Unzip | ||||
| 	osRename        = os.Rename | ||||
| 	osStat          = os.Stat | ||||
| 	doublestarGlob  = doublestar.Glob | ||||
| @@ -95,7 +93,8 @@ func sonarExecuteScan(config sonarExecuteScanOptions, _ *telemetry.CustomData, i | ||||
| 	} | ||||
|  | ||||
| 	influx.step_data.fields.sonar = false | ||||
| 	if err := runSonar(config, downloadClient, &runner, apiClient, influx); err != nil { | ||||
| 	fileUtils := piperutils.Files{} | ||||
| 	if err := runSonar(config, downloadClient, &runner, apiClient, &fileUtils, influx); err != nil { | ||||
| 		if log.GetErrorCategory() == log.ErrorUndefined && runner.GetExitCode() == 2 { | ||||
| 			// see https://github.com/SonarSource/sonar-scanner-cli/blob/adb67d645c3bcb9b46f29dea06ba082ebec9ba7a/src/main/java/org/sonarsource/scanner/cli/Exit.java#L25 | ||||
| 			log.SetErrorCategory(log.ErrorConfiguration) | ||||
| @@ -105,7 +104,7 @@ func sonarExecuteScan(config sonarExecuteScanOptions, _ *telemetry.CustomData, i | ||||
| 	influx.step_data.fields.sonar = true | ||||
| } | ||||
|  | ||||
| func runSonar(config sonarExecuteScanOptions, client piperhttp.Downloader, runner command.ExecRunner, apiClient SonarUtils.Sender, influx *sonarExecuteScanInflux) error { | ||||
| func runSonar(config sonarExecuteScanOptions, client piperhttp.Downloader, runner command.ExecRunner, apiClient SonarUtils.Sender, utils piperutils.FileUtils, influx *sonarExecuteScanInflux) error { | ||||
| 	// Set config based on orchestrator-specific environment variables | ||||
| 	detectParametersFromCI(&config) | ||||
|  | ||||
| @@ -168,7 +167,7 @@ func runSonar(config sonarExecuteScanOptions, client piperhttp.Downloader, runne | ||||
| 		sonar.options = append(sonar.options, config.Options...) | ||||
| 	} | ||||
|  | ||||
| 	sonar.options = SliceUtils.PrefixIfNeeded(SliceUtils.Trim(sonar.options), "-D") | ||||
| 	sonar.options = piperutils.PrefixIfNeeded(piperutils.Trim(sonar.options), "-D") | ||||
|  | ||||
| 	log.Entry(). | ||||
| 		WithField("command", sonar.binary). | ||||
| @@ -194,13 +193,13 @@ func runSonar(config sonarExecuteScanOptions, client piperhttp.Downloader, runne | ||||
| 		return nil | ||||
| 	} | ||||
| 	// write links JSON | ||||
| 	links := []StepResults.Path{ | ||||
| 	links := []piperutils.Path{ | ||||
| 		{ | ||||
| 			Target: taskReport.DashboardURL, | ||||
| 			Name:   "Sonar Web UI", | ||||
| 		}, | ||||
| 	} | ||||
| 	StepResults.PersistReportsAndLinks("sonarExecuteScan", sonar.workingDir, nil, links) | ||||
| 	piperutils.PersistReportsAndLinks("sonarExecuteScan", sonar.workingDir, utils, nil, links) | ||||
|  | ||||
| 	if len(config.Token) == 0 { | ||||
| 		log.Entry().Warn("no measurements are fetched due to missing credentials") | ||||
| @@ -278,7 +277,7 @@ func runSonar(config sonarExecuteScanOptions, client piperhttp.Downloader, runne | ||||
| // isInOptions returns true, if the given property is already provided in config.Options. | ||||
| func isInOptions(config sonarExecuteScanOptions, property string) bool { | ||||
| 	property = strings.TrimSuffix(property, "=") | ||||
| 	return SliceUtils.ContainsStringPart(config.Options, property) | ||||
| 	return piperutils.ContainsStringPart(config.Options, property) | ||||
| } | ||||
|  | ||||
| func addJavaBinaries() { | ||||
|   | ||||
| @@ -17,11 +17,11 @@ import ( | ||||
|  | ||||
| 	piperHttp "github.com/SAP/jenkins-library/pkg/http" | ||||
| 	"github.com/SAP/jenkins-library/pkg/mock" | ||||
| 	FileUtils "github.com/SAP/jenkins-library/pkg/piperutils" | ||||
| 	"github.com/SAP/jenkins-library/pkg/piperutils" | ||||
| 	SonarUtils "github.com/SAP/jenkins-library/pkg/sonar" | ||||
| ) | ||||
|  | ||||
| //TODO: extract to mock package | ||||
| // TODO: extract to mock package | ||||
| type mockDownloader struct { | ||||
| 	shouldFail    bool | ||||
| 	requestedURL  []string | ||||
| @@ -92,8 +92,8 @@ func mockGlob(matchesForPatterns map[string][]string) func(pattern string) ([]st | ||||
| } | ||||
|  | ||||
| func createTaskReportFile(t *testing.T, workingDir string) { | ||||
| 	require.NoError(t, os.MkdirAll(filepath.Join(workingDir, ".scannerwork"), 0755)) | ||||
| 	require.NoError(t, ioutil.WriteFile(filepath.Join(workingDir, ".scannerwork", "report-task.txt"), []byte(taskReportContent), 0755)) | ||||
| 	require.NoError(t, os.MkdirAll(filepath.Join(workingDir, ".scannerwork"), 0o755)) | ||||
| 	require.NoError(t, ioutil.WriteFile(filepath.Join(workingDir, ".scannerwork", "report-task.txt"), []byte(taskReportContent), 0o755)) | ||||
| 	require.FileExists(t, filepath.Join(workingDir, ".scannerwork", "report-task.txt")) | ||||
| } | ||||
|  | ||||
| @@ -175,7 +175,7 @@ func TestRunSonar(t *testing.T) { | ||||
| 		} | ||||
| 		fileUtilsExists = mockFileUtilsExists(true) | ||||
| 		// test | ||||
| 		err := runSonar(options, &mockDownloadClient, &mockRunner, apiClient, &sonarExecuteScanInflux{}) | ||||
| 		err := runSonar(options, &mockDownloadClient, &mockRunner, apiClient, &mock.FilesMock{}, &sonarExecuteScanInflux{}) | ||||
| 		// assert | ||||
| 		assert.NoError(t, err) | ||||
| 		assert.Contains(t, sonar.options, "-Dsonar.projectVersion=1") | ||||
| @@ -183,8 +183,6 @@ func TestRunSonar(t *testing.T) { | ||||
| 		assert.Contains(t, sonar.environment, "SONAR_HOST_URL="+sonarServerURL) | ||||
| 		assert.Contains(t, sonar.environment, "SONAR_TOKEN=secret-ABC") | ||||
| 		assert.Contains(t, sonar.environment, "SONAR_SCANNER_OPTS=-Djavax.net.ssl.trustStore="+filepath.Join(getWorkingDir(), ".certificates", "cacerts")+" -Djavax.net.ssl.trustStorePassword=changeit") | ||||
| 		assert.FileExists(t, filepath.Join(sonar.workingDir, "sonarExecuteScan_reports.json")) | ||||
| 		assert.FileExists(t, filepath.Join(sonar.workingDir, "sonarExecuteScan_links.json")) | ||||
| 	}) | ||||
| 	t.Run("with custom options", func(t *testing.T) { | ||||
| 		// init | ||||
| @@ -203,10 +201,10 @@ func TestRunSonar(t *testing.T) { | ||||
| 		} | ||||
| 		fileUtilsExists = mockFileUtilsExists(true) | ||||
| 		defer func() { | ||||
| 			fileUtilsExists = FileUtils.FileExists | ||||
| 			fileUtilsExists = piperutils.FileExists | ||||
| 		}() | ||||
| 		// test | ||||
| 		err := runSonar(options, &mockDownloadClient, &mockRunner, apiClient, &sonarExecuteScanInflux{}) | ||||
| 		err := runSonar(options, &mockDownloadClient, &mockRunner, apiClient, &mock.FilesMock{}, &sonarExecuteScanInflux{}) | ||||
| 		// assert | ||||
| 		assert.NoError(t, err) | ||||
| 		assert.Contains(t, sonar.options, "-Dsonar.projectKey=piper") | ||||
| @@ -235,7 +233,7 @@ func TestRunSonar(t *testing.T) { | ||||
| 		osStat = mockOsStat(existsMap) | ||||
|  | ||||
| 		defer func() { | ||||
| 			fileUtilsExists = FileUtils.FileExists | ||||
| 			fileUtilsExists = piperutils.FileExists | ||||
| 			doublestarGlob = doublestar.Glob | ||||
| 			osStat = os.Stat | ||||
| 		}() | ||||
| @@ -244,7 +242,7 @@ func TestRunSonar(t *testing.T) { | ||||
| 			PullRequestProvider: "GitHub", | ||||
| 		} | ||||
| 		// test | ||||
| 		err := runSonar(options, &mockDownloadClient, &mockRunner, apiClient, &sonarExecuteScanInflux{}) | ||||
| 		err := runSonar(options, &mockDownloadClient, &mockRunner, apiClient, &mock.FilesMock{}, &sonarExecuteScanInflux{}) | ||||
| 		// assert | ||||
| 		assert.NoError(t, err) | ||||
| 		assert.Contains(t, sonar.options, fmt.Sprintf("-Dsonar.java.binaries=%s,%s,%s", | ||||
| @@ -274,7 +272,7 @@ func TestRunSonar(t *testing.T) { | ||||
| 		osStat = mockOsStat(existsMap) | ||||
|  | ||||
| 		defer func() { | ||||
| 			fileUtilsExists = FileUtils.FileExists | ||||
| 			fileUtilsExists = piperutils.FileExists | ||||
| 			doublestarGlob = doublestar.Glob | ||||
| 			osStat = os.Stat | ||||
| 		}() | ||||
| @@ -284,7 +282,7 @@ func TestRunSonar(t *testing.T) { | ||||
| 			PullRequestProvider: "GitHub", | ||||
| 		} | ||||
| 		// test | ||||
| 		err := runSonar(options, &mockDownloadClient, &mockRunner, apiClient, &sonarExecuteScanInflux{}) | ||||
| 		err := runSonar(options, &mockDownloadClient, &mockRunner, apiClient, &mock.FilesMock{}, &sonarExecuteScanInflux{}) | ||||
| 		// assert | ||||
| 		assert.NoError(t, err) | ||||
| 		assert.NotContains(t, sonar.options, fmt.Sprintf("-Dsonar.java.binaries=%s", | ||||
| @@ -313,10 +311,10 @@ func TestRunSonar(t *testing.T) { | ||||
| 		defer func() { GeneralConfig.Verbose = false }() | ||||
| 		fileUtilsExists = mockFileUtilsExists(true) | ||||
| 		defer func() { | ||||
| 			fileUtilsExists = FileUtils.FileExists | ||||
| 			fileUtilsExists = piperutils.FileExists | ||||
| 		}() | ||||
| 		// test | ||||
| 		err := runSonar(options, &mockDownloadClient, &mockRunner, apiClient, &sonarExecuteScanInflux{}) | ||||
| 		err := runSonar(options, &mockDownloadClient, &mockRunner, apiClient, &mock.FilesMock{}, &sonarExecuteScanInflux{}) | ||||
| 		// assert | ||||
| 		assert.NoError(t, err) | ||||
| 		assert.Contains(t, sonar.options, "-Dsonar.projectKey=mock-project-key") | ||||
| @@ -430,7 +428,7 @@ func TestSonarLoadScanner(t *testing.T) { | ||||
| 		osRename = mockOsRename(t, "sonar-scanner-4.6.2.2472-linux", ".sonar-scanner") | ||||
| 		defer func() { | ||||
| 			execLookPath = exec.LookPath | ||||
| 			fileUtilsUnzip = FileUtils.Unzip | ||||
| 			fileUtilsUnzip = piperutils.Unzip | ||||
| 			osRename = os.Rename | ||||
| 		}() | ||||
| 		// test | ||||
| @@ -455,7 +453,7 @@ func TestSonarLoadCertificates(t *testing.T) { | ||||
| 			options:     []string{}, | ||||
| 		} | ||||
| 		fileUtilsExists = mockFileUtilsExists(true) | ||||
| 		defer func() { fileUtilsExists = FileUtils.FileExists }() | ||||
| 		defer func() { fileUtilsExists = piperutils.FileExists }() | ||||
| 		// test | ||||
| 		err := loadCertificates([]string{}, &mockClient, &mockRunner) | ||||
| 		// assert | ||||
|   | ||||
| @@ -226,7 +226,7 @@ func runWhitesourceScan(ctx context.Context, config *ScanOptions, scan *ws.Scan, | ||||
| 	log.Entry().Info("-----------------------------------------------------") | ||||
|  | ||||
| 	paths, err := checkAndReportScanResults(ctx, config, scan, utils, sys, influx) | ||||
| 	piperutils.PersistReportsAndLinks("whitesourceExecuteScan", "", paths, nil) | ||||
| 	piperutils.PersistReportsAndLinks("whitesourceExecuteScan", "", utils, paths, nil) | ||||
| 	persistScannedProjects(config, scan, commonPipelineEnvironment) | ||||
| 	if err != nil { | ||||
| 		return errors.Wrapf(err, "failed to check and report scan results") | ||||
| @@ -273,7 +273,7 @@ func checkAndReportScanResults(ctx context.Context, config *ScanOptions, scan *w | ||||
|  | ||||
| 	// create toolrecord file | ||||
| 	// tbd - how to handle verifyOnly | ||||
| 	toolRecordFileName, err := createToolRecordWhitesource("./", config, scan) | ||||
| 	toolRecordFileName, err := createToolRecordWhitesource(utils, "./", config, scan) | ||||
| 	if err != nil { | ||||
| 		// do not fail until the framework is well established | ||||
| 		log.Entry().Warning("TR_WHITESOURCE: Failed to create toolrecord file ...", err) | ||||
| @@ -750,7 +750,7 @@ func newVulnerabilityExcelReport(alerts []ws.Alert, config *ScanOptions, utils w | ||||
| 		return err | ||||
| 	} | ||||
| 	filePath := piperutils.Path{Name: "aggregated-vulnerabilities", Target: fileName} | ||||
| 	piperutils.PersistReportsAndLinks("whitesourceExecuteScan", "", []piperutils.Path{filePath}, nil) | ||||
| 	piperutils.PersistReportsAndLinks("whitesourceExecuteScan", "", utils, []piperutils.Path{filePath}, nil) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| @@ -812,7 +812,7 @@ func newLibraryCSVReport(libraries map[string][]ws.Library, config *ScanOptions, | ||||
| 		return errors.Wrapf(err, "failed to write file: %s", fileName) | ||||
| 	} | ||||
| 	filePath := piperutils.Path{Name: "aggregated-libraries", Target: fileName} | ||||
| 	piperutils.PersistReportsAndLinks("whitesourceExecuteScan", "", []piperutils.Path{filePath}, nil) | ||||
| 	piperutils.PersistReportsAndLinks("whitesourceExecuteScan", "", utils, []piperutils.Path{filePath}, nil) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| @@ -830,8 +830,8 @@ func persistScannedProjects(config *ScanOptions, scan *ws.Scan, commonPipelineEn | ||||
|  | ||||
| // create toolrecord file for whitesource | ||||
| // | ||||
| func createToolRecordWhitesource(workspace string, config *whitesourceExecuteScanOptions, scan *ws.Scan) (string, error) { | ||||
| 	record := toolrecord.New(workspace, "whitesource", config.ServiceURL) | ||||
| func createToolRecordWhitesource(utils whitesourceUtils, workspace string, config *whitesourceExecuteScanOptions, scan *ws.Scan) (string, error) { | ||||
| 	record := toolrecord.New(utils, workspace, "whitesource", config.ServiceURL) | ||||
| 	wsUiRoot := "https://saas.whitesourcesoftware.com" | ||||
| 	productURL := wsUiRoot + "/Wss/WSS.html#!product;token=" + config.ProductToken | ||||
| 	err := record.AddKeyData("product", | ||||
|   | ||||
| @@ -8,7 +8,6 @@ import ( | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/SAP/jenkins-library/pkg/mock" | ||||
| 	"github.com/SAP/jenkins-library/pkg/piperenv" | ||||
| 	"github.com/SAP/jenkins-library/pkg/piperutils" | ||||
| 	"github.com/SAP/jenkins-library/pkg/reporting" | ||||
| 	"github.com/SAP/jenkins-library/pkg/versioning" | ||||
| @@ -663,7 +662,8 @@ func TestAggregateVersionWideLibraries(t *testing.T) { | ||||
| 			contents, _ := utils.FileRead(resource) | ||||
| 			asString := string(contents) | ||||
| 			assert.Equal(t, "Library Name, Project Name\nmock-library, mock-project\n", asString) | ||||
| 			assert.NotEmpty(t, piperenv.GetParameter("", "whitesourceExecuteScan_reports.json")) | ||||
| 			c, _ := utils.ReadFile("/whitesourceExecuteScan_reports.json") | ||||
| 			assert.NotEmpty(t, c) | ||||
| 		} | ||||
| 	}) | ||||
| } | ||||
| @@ -692,7 +692,8 @@ func TestAggregateVersionWideVulnerabilities(t *testing.T) { | ||||
| 		sheetContents, err := utils.FileRead(reportSheet) | ||||
| 		assert.NoError(t, err) | ||||
| 		assert.NotEmpty(t, sheetContents) | ||||
| 		assert.NotEmpty(t, piperenv.GetParameter("", "whitesourceExecuteScan_reports.json")) | ||||
| 		c, _ := utils.ReadFile("whitesourceExecuteScan_reports.json") | ||||
| 		assert.NotEmpty(t, c) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -8,11 +8,13 @@ import ( | ||||
| 	"github.com/SAP/jenkins-library/pkg/command" | ||||
| 	piperhttp "github.com/SAP/jenkins-library/pkg/http" | ||||
| 	"github.com/SAP/jenkins-library/pkg/log" | ||||
| 	"github.com/SAP/jenkins-library/pkg/piperutils" | ||||
| ) | ||||
|  | ||||
| type AakUtils interface { | ||||
| 	command.ExecRunner | ||||
| 	abapbuild.HTTPSendLoader | ||||
| 	piperutils.FileUtils | ||||
| 	ReadAddonDescriptor(FileName string) (abaputils.AddonDescriptor, error) | ||||
| 	GetMaxRuntime() time.Duration | ||||
| 	GetPollingInterval() time.Duration | ||||
| @@ -21,6 +23,7 @@ type AakUtils interface { | ||||
| type AakBundle struct { | ||||
| 	*command.Command | ||||
| 	*piperhttp.Client | ||||
| 	*piperutils.Files | ||||
| 	maxRuntime      time.Duration | ||||
| 	pollingInterval time.Duration | ||||
| } | ||||
|   | ||||
| @@ -9,12 +9,14 @@ import ( | ||||
| 	abapbuild "github.com/SAP/jenkins-library/pkg/abap/build" | ||||
| 	"github.com/SAP/jenkins-library/pkg/abaputils" | ||||
| 	"github.com/SAP/jenkins-library/pkg/mock" | ||||
| 	"github.com/SAP/jenkins-library/pkg/piperutils" | ||||
| 	"github.com/pkg/errors" | ||||
| ) | ||||
|  | ||||
| type AakBundleMock struct { | ||||
| 	*mock.ExecMockRunner | ||||
| 	*abaputils.ClientMock | ||||
| 	*mock.FilesMock | ||||
| 	maxRuntime time.Duration | ||||
| } | ||||
|  | ||||
| @@ -23,6 +25,7 @@ func NewAakBundleMock() *AakBundleMock { | ||||
| 		ExecMockRunner: &mock.ExecMockRunner{}, | ||||
| 		ClientMock:     &abaputils.ClientMock{}, | ||||
| 		maxRuntime:     1 * time.Second, | ||||
| 		FilesMock:      &mock.FilesMock{}, | ||||
| 	} | ||||
| 	return &utils | ||||
| } | ||||
| @@ -100,6 +103,7 @@ func (bundle *AakBundleMock) ReadAddonDescriptor(FileName string) (abaputils.Add | ||||
| type AakBundleMockNewMC struct { | ||||
| 	*mock.ExecMockRunner | ||||
| 	*abapbuild.MockClient | ||||
| 	*piperutils.Files | ||||
| 	maxRuntime time.Duration | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -440,7 +440,7 @@ func (b *Build) DownloadResults(filenames []string, basePath string, filenamePre | ||||
| } | ||||
|  | ||||
| // PublishAllDownloadedResults : publishes all build artefacts which were downloaded before | ||||
| func (b *Build) PublishAllDownloadedResults(stepname string, publish Publish) { | ||||
| func (b *Build) PublishAllDownloadedResults(stepname string, utils piperutils.FileUtils) { | ||||
| 	var filesToPublish []piperutils.Path | ||||
| 	for i_task := range b.Tasks { | ||||
| 		for i_result := range b.Tasks[i_task].Results { | ||||
| @@ -451,12 +451,14 @@ func (b *Build) PublishAllDownloadedResults(stepname string, publish Publish) { | ||||
| 		} | ||||
| 	} | ||||
| 	if len(filesToPublish) > 0 { | ||||
| 		publish.PersistReportsAndLinks(stepname, "", filesToPublish, nil) | ||||
| 		if err := piperutils.PersistReportsAndLinks(stepname, "", utils, filesToPublish, nil); err != nil { | ||||
| 			log.Entry().WithError(err).Error("failed to persist reports") | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // PublishDownloadedResults : Publishes build artefacts specified in filenames | ||||
| func (b *Build) PublishDownloadedResults(stepname string, filenames []string, publish Publish) error { | ||||
| func (b *Build) PublishDownloadedResults(stepname string, filenames []string, utils piperutils.FileUtils) error { | ||||
| 	var filesToPublish []piperutils.Path | ||||
| 	for i := range filenames { | ||||
| 		result, err := b.GetResult(filenames[i]) | ||||
| @@ -472,7 +474,9 @@ func (b *Build) PublishDownloadedResults(stepname string, filenames []string, pu | ||||
| 		} | ||||
| 	} | ||||
| 	if len(filesToPublish) > 0 { | ||||
| 		publish.PersistReportsAndLinks(stepname, "", filesToPublish, nil) | ||||
| 		if err := piperutils.PersistReportsAndLinks(stepname, "", utils, filesToPublish, nil); err != nil { | ||||
| 			log.Entry().WithError(err).Error("failed to persist reports") | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| @@ -594,12 +598,3 @@ func unmarshalTasks(body []byte, connector Connector) ([]task, error) { | ||||
| 	} | ||||
| 	return tasks, nil | ||||
| } | ||||
|  | ||||
| // *****************publish ******************************* | ||||
| type Publish interface { | ||||
| 	PersistReportsAndLinks(stepName, workspace string, reports, links []piperutils.Path) | ||||
| } | ||||
|  | ||||
| func PersistReportsAndLinks(stepName, workspace string, reports, links []piperutils.Path) { | ||||
| 	piperutils.PersistReportsAndLinks(stepName, workspace, reports, links) | ||||
| } | ||||
|   | ||||
| @@ -34,8 +34,7 @@ func (c *ClMock) SetOptions(opts piperhttp.ClientOptions) {} | ||||
| // SendRequest : BF Send Fake request | ||||
| func (c *ClMock) SendRequest(method string, url string, bdy io.Reader, hdr http.Header, cookies []*http.Cookie) (*http.Response, error) { | ||||
| 	if method == "GET" || method == "POST" { | ||||
| 		var body []byte | ||||
| 		body = []byte(fakeResponse(method, url)) | ||||
| 		body := []byte(fakeResponse(method, url)) | ||||
| 		return &http.Response{ | ||||
| 			StatusCode: c.StatusCode, | ||||
| 			Body:       ioutil.NopCloser(bytes.NewReader(body)), | ||||
|   | ||||
| @@ -7,18 +7,10 @@ import ( | ||||
| 	"time" | ||||
|  | ||||
| 	piperhttp "github.com/SAP/jenkins-library/pkg/http" | ||||
| 	"github.com/SAP/jenkins-library/pkg/piperutils" | ||||
| 	"github.com/SAP/jenkins-library/pkg/mock" | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| ) | ||||
|  | ||||
| type mockPublish struct { | ||||
| 	reports []piperutils.Path | ||||
| } | ||||
|  | ||||
| func (mP *mockPublish) PersistReportsAndLinks(stepName, workspace string, reports, links []piperutils.Path) { | ||||
| 	mP.reports = reports | ||||
| } | ||||
|  | ||||
| func testSetup(client piperhttp.Sender, buildID string) Build { | ||||
| 	conn := new(Connector) | ||||
| 	conn.Client = client | ||||
| @@ -370,36 +362,26 @@ func TestPublishAllDownloadedResults(t *testing.T) { | ||||
| 	t.Run("Something was downloaded", func(t *testing.T) { | ||||
| 		//arrange | ||||
| 		build := GetMockBuildTestDownloadPublish() | ||||
| 		mP := mockPublish{} | ||||
| 		files := mock.FilesMock{} | ||||
| 		build.Tasks[1].Results[0].SavedFilename = "File1" | ||||
| 		build.Tasks[1].Results[0].DownloadPath = "Dir1/File1" | ||||
| 		build.Tasks[1].Results[2].SavedFilename = "File3" | ||||
| 		build.Tasks[1].Results[2].DownloadPath = "File3" | ||||
| 		//act | ||||
| 		build.PublishAllDownloadedResults("MyStep", &mP) | ||||
| 		build.PublishAllDownloadedResults("MyStep", &files) | ||||
| 		//assert | ||||
| 		publishedFiles := []piperutils.Path{ | ||||
| 			{ | ||||
| 				Target:    "Dir1/File1", | ||||
| 				Name:      "File1", | ||||
| 				Mandatory: true, | ||||
| 			}, | ||||
| 			{ | ||||
| 				Target:    "File3", | ||||
| 				Name:      "File3", | ||||
| 				Mandatory: true, | ||||
| 			}, | ||||
| 		} | ||||
| 		assert.Equal(t, publishedFiles, mP.reports) | ||||
| 		assert.True(t, files.HasFile("/MyStep_reports.json")) | ||||
| 		assert.True(t, files.HasFile("/MyStep_links.json")) | ||||
| 	}) | ||||
| 	t.Run("Nothing was downloaded", func(t *testing.T) { | ||||
| 		//arrange | ||||
| 		build := GetMockBuildTestDownloadPublish() | ||||
| 		mP := mockPublish{} | ||||
| 		files := mock.FilesMock{} | ||||
| 		//act | ||||
| 		build.PublishAllDownloadedResults("MyStep", &mP) | ||||
| 		build.PublishAllDownloadedResults("MyStep", &files) | ||||
| 		//assert | ||||
| 		assert.Equal(t, 0, len(mP.reports)) | ||||
| 		assert.False(t, files.HasFile("/MyStep_reports.json")) | ||||
| 		assert.False(t, files.HasFile("/MyStep_links.json")) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| @@ -408,37 +390,28 @@ func TestPublishDownloadedResults(t *testing.T) { | ||||
| 	t.Run("Publish downloaded files", func(t *testing.T) { | ||||
| 		//arrange | ||||
| 		build := GetMockBuildTestDownloadPublish() | ||||
| 		mP := mockPublish{} | ||||
| 		files := mock.FilesMock{} | ||||
| 		build.Tasks[1].Results[0].SavedFilename = "SuperFile_File1" | ||||
| 		build.Tasks[1].Results[0].DownloadPath = "Dir1/SuperFile_File1" | ||||
| 		build.Tasks[1].Results[2].SavedFilename = "File3" | ||||
| 		build.Tasks[1].Results[2].DownloadPath = "File3" | ||||
| 		//act | ||||
| 		err := build.PublishDownloadedResults("MyStep", filenames, &mP) | ||||
| 		err := build.PublishDownloadedResults("MyStep", filenames, &files) | ||||
| 		//assert | ||||
| 		assert.NoError(t, err) | ||||
| 		publishedFiles := []piperutils.Path{ | ||||
| 			{ | ||||
| 				Target:    "Dir1/SuperFile_File1", | ||||
| 				Name:      "SuperFile_File1", | ||||
| 				Mandatory: true, | ||||
| 			}, | ||||
| 			{ | ||||
| 				Target:    "File3", | ||||
| 				Name:      "File3", | ||||
| 				Mandatory: true, | ||||
| 			}, | ||||
| 		} | ||||
| 		assert.Equal(t, publishedFiles, mP.reports) | ||||
|  | ||||
| 		assert.True(t, files.HasFile("/MyStep_reports.json")) | ||||
| 		assert.True(t, files.HasFile("/MyStep_links.json")) | ||||
|  | ||||
| 	}) | ||||
| 	t.Run("Try to publish file which was not downloaded", func(t *testing.T) { | ||||
| 		//arrange | ||||
| 		build := GetMockBuildTestDownloadPublish() | ||||
| 		mP := mockPublish{} | ||||
| 		files := mock.FilesMock{} | ||||
| 		build.Tasks[1].Results[0].SavedFilename = "SuperFile_File1" | ||||
| 		build.Tasks[1].Results[0].DownloadPath = "Dir1/SuperFile_File1" | ||||
| 		//act | ||||
| 		err := build.PublishDownloadedResults("MyStep", filenames, &mP) | ||||
| 		err := build.PublishDownloadedResults("MyStep", filenames, &files) | ||||
| 		//assert | ||||
| 		assert.Error(t, err) | ||||
| 	}) | ||||
|   | ||||
| @@ -92,12 +92,22 @@ func TestCreateJSONReport(t *testing.T) { | ||||
| 	assert.Equal(t, 5, reportingData.InformationTotal) | ||||
| 	assert.Equal(t, 0, reportingData.InformationAudited) | ||||
| 	assert.Equal(t, 2, len(*reportingData.LowPerQuery)) | ||||
| 	assert.Equal(t, "Low_Query_Name_1", (*reportingData.LowPerQuery)[0].QueryName) | ||||
| 	assert.Equal(t, 0, (*reportingData.LowPerQuery)[0].Audited) | ||||
| 	assert.Equal(t, 4, (*reportingData.LowPerQuery)[0].Total) | ||||
| 	assert.Equal(t, "Low_Query_Name_2", (*reportingData.LowPerQuery)[1].QueryName) | ||||
| 	assert.Equal(t, 5, (*reportingData.LowPerQuery)[1].Audited) | ||||
| 	assert.Equal(t, 5, (*reportingData.LowPerQuery)[1].Total) | ||||
| 	if (*reportingData.LowPerQuery)[0].QueryName == "Low_Query_Name_1" { | ||||
| 		assert.Equal(t, "Low_Query_Name_1", (*reportingData.LowPerQuery)[0].QueryName) | ||||
| 		assert.Equal(t, 0, (*reportingData.LowPerQuery)[0].Audited) | ||||
| 		assert.Equal(t, 4, (*reportingData.LowPerQuery)[0].Total) | ||||
| 		assert.Equal(t, "Low_Query_Name_2", (*reportingData.LowPerQuery)[1].QueryName) | ||||
| 		assert.Equal(t, 5, (*reportingData.LowPerQuery)[1].Audited) | ||||
| 		assert.Equal(t, 5, (*reportingData.LowPerQuery)[1].Total) | ||||
| 	} else { | ||||
| 		assert.Equal(t, "Low_Query_Name_1", (*reportingData.LowPerQuery)[1].QueryName) | ||||
| 		assert.Equal(t, 0, (*reportingData.LowPerQuery)[1].Audited) | ||||
| 		assert.Equal(t, 4, (*reportingData.LowPerQuery)[1].Total) | ||||
| 		assert.Equal(t, "Low_Query_Name_2", (*reportingData.LowPerQuery)[0].QueryName) | ||||
| 		assert.Equal(t, 5, (*reportingData.LowPerQuery)[0].Audited) | ||||
| 		assert.Equal(t, 5, (*reportingData.LowPerQuery)[0].Total) | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| func TestJsonReportWithNoLowVulnData(t *testing.T) { | ||||
|   | ||||
| @@ -47,3 +47,16 @@ func (_m *HadolintPiperFileUtils) FileWrite(filename string, data []byte, perm o | ||||
|  | ||||
| 	return r0 | ||||
| } | ||||
|  | ||||
| func (_m *HadolintPiperFileUtils) WriteFile(filename string, data []byte, perm os.FileMode) error { | ||||
| 	ret := _m.Called(filename, data, perm) | ||||
|  | ||||
| 	var r0 error | ||||
| 	if rf, ok := ret.Get(0).(func(string, []byte, os.FileMode) error); ok { | ||||
| 		r0 = rf(filename, data, perm) | ||||
| 	} else { | ||||
| 		r0 = ret.Error(0) | ||||
| 	} | ||||
|  | ||||
| 	return r0 | ||||
| } | ||||
|   | ||||
| @@ -20,8 +20,8 @@ import ( | ||||
| var dirContent []byte | ||||
|  | ||||
| const ( | ||||
| 	defaultFileMode os.FileMode = 0644 | ||||
| 	defaultDirMode  os.FileMode = 0755 | ||||
| 	defaultFileMode os.FileMode = 0o644 | ||||
| 	defaultDirMode  os.FileMode = 0o755 | ||||
| ) | ||||
|  | ||||
| type fileInfoMock struct { | ||||
| @@ -50,7 +50,7 @@ func (p *fileProperties) isDir() bool { | ||||
| 	return p.content == &dirContent | ||||
| } | ||||
|  | ||||
| //FilesMock implements the functions from piperutils.Files with an in-memory file system. | ||||
| // FilesMock implements the functions from piperutils.Files with an in-memory file system. | ||||
| type FilesMock struct { | ||||
| 	files            map[string]*fileProperties | ||||
| 	writtenFiles     []string | ||||
| @@ -274,6 +274,11 @@ func (f *FilesMock) FileRead(path string) ([]byte, error) { | ||||
| 	return *props.content, nil | ||||
| } | ||||
|  | ||||
| // ReadFile can be used as replacement for os.ReadFile in a compatible manner | ||||
| func (f *FilesMock) ReadFile(name string) ([]byte, error) { | ||||
| 	return f.FileRead(name) | ||||
| } | ||||
|  | ||||
| // FileWrite just forwards to AddFile(), i.e. the content is associated with the given path. | ||||
| func (f *FilesMock) FileWrite(path string, content []byte, mode os.FileMode) error { | ||||
| 	if f.FileWriteError != nil { | ||||
| @@ -288,6 +293,11 @@ func (f *FilesMock) FileWrite(path string, content []byte, mode os.FileMode) err | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // WriteFile can be used as replacement for os.WriteFile in a compatible manner | ||||
| func (f *FilesMock) WriteFile(filename string, data []byte, perm os.FileMode) error { | ||||
| 	return f.FileWrite(filename, data, perm) | ||||
| } | ||||
|  | ||||
| // RemoveAll is a proxy for FileRemove | ||||
| func (f *FilesMock) RemoveAll(path string) error { | ||||
| 	return f.FileRemove(path) | ||||
| @@ -378,7 +388,7 @@ func (f *FilesMock) TempDir(baseDir string, pattern string) (string, error) { | ||||
| 		tmpDir = fmt.Sprintf("%s/%stest", baseDir, pattern) | ||||
| 	} | ||||
|  | ||||
| 	err := f.MkdirAll(tmpDir, 0755) | ||||
| 	err := f.MkdirAll(tmpDir, 0o755) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| @@ -621,5 +631,5 @@ func (f *FilesMock) Open(name string) (io.ReadWriteCloser, error) { | ||||
| } | ||||
|  | ||||
| func (f *FilesMock) Create(name string) (io.ReadWriteCloser, error) { | ||||
| 	return f.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666) | ||||
| 	return f.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o666) | ||||
| } | ||||
|   | ||||
| @@ -26,7 +26,9 @@ type FileUtils interface { | ||||
| 	Copy(src, dest string) (int64, error) | ||||
| 	Move(src, dest string) error | ||||
| 	FileRead(path string) ([]byte, error) | ||||
| 	ReadFile(path string) ([]byte, error) | ||||
| 	FileWrite(path string, content []byte, perm os.FileMode) error | ||||
| 	WriteFile(path string, content []byte, perm os.FileMode) error | ||||
| 	FileRemove(path string) error | ||||
| 	MkdirAll(path string, perm os.FileMode) error | ||||
| 	Chmod(path string, mode os.FileMode) error | ||||
| @@ -44,15 +46,14 @@ type FileUtils interface { | ||||
| } | ||||
| 
 | ||||
| // Files ... | ||||
| type Files struct { | ||||
| } | ||||
| type Files struct{} | ||||
| 
 | ||||
| // TempDir creates a temporary directory | ||||
| func (f Files) TempDir(dir, pattern string) (name string, err error) { | ||||
| 	if len(dir) == 0 { | ||||
| 		// lazy init system temp dir in case it doesn't exist | ||||
| 		if exists, _ := f.DirExists(os.TempDir()); !exists { | ||||
| 			f.MkdirAll(os.TempDir(), 0666) | ||||
| 			f.MkdirAll(os.TempDir(), 0o666) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| @@ -94,9 +95,7 @@ func (f Files) DirExists(path string) (bool, error) { | ||||
| 
 | ||||
| // Copy ... | ||||
| func (f Files) Copy(src, dst string) (int64, error) { | ||||
| 
 | ||||
| 	exists, err := f.FileExists(src) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		return 0, err | ||||
| 	} | ||||
| @@ -126,6 +125,7 @@ func (f Files) Copy(src, dst string) (int64, error) { | ||||
| 	return nBytes, err | ||||
| } | ||||
| 
 | ||||
| // Move will move files from src to dst | ||||
| func (f Files) Move(src, dst string) error { | ||||
| 	if exists, err := f.FileExists(src); err != nil { | ||||
| 		return err | ||||
| @@ -140,7 +140,7 @@ func (f Files) Move(src, dst string) error { | ||||
| 	return f.FileRemove(src) | ||||
| } | ||||
| 
 | ||||
| //Chmod is a wrapper for os.Chmod(). | ||||
| // Chmod is a wrapper for os.Chmod(). | ||||
| func (f Files) Chmod(path string, mode os.FileMode) error { | ||||
| 	return os.Chmod(path, mode) | ||||
| } | ||||
| @@ -170,7 +170,6 @@ func (f Files) Chmod(path string, mode os.FileMode) error { | ||||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
| // SOFTWARE. | ||||
| func Unzip(src, dest string) ([]string, error) { | ||||
| 
 | ||||
| 	var filenames []string | ||||
| 
 | ||||
| 	r, err := zip.OpenReader(src) | ||||
| @@ -236,18 +235,15 @@ func Unzip(src, dest string) ([]string, error) { | ||||
| // stripComponentLevel = 2 -> parentFolder/childFolder/someFile.Txt -> someFile.Txt | ||||
| // when stripCompenent in 0 the untar will retain the original tar folder structure | ||||
| // when stripCompmenet is greater than 0 the expectation is all files must be under that level folder and if not there is a hard check and failure condition | ||||
| 
 | ||||
| func Untar(src string, dest string, stripComponentLevel int) error { | ||||
| 	file, err := os.Open(src) | ||||
| 	defer file.Close() | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("unable to open src: %v", err) | ||||
| 	} | ||||
| 	defer file.Close() | ||||
| 
 | ||||
| 	if b, err := isFileGzipped(src); err == nil && b { | ||||
| 		zr, err := gzip.NewReader(file) | ||||
| 
 | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("requires gzip-compressed body: %v", err) | ||||
| 		} | ||||
| @@ -301,7 +297,7 @@ func untar(r io.Reader, dir string, level int) (err error) { | ||||
| 			// write will fail with the same error. | ||||
| 			dir := filepath.Dir(abs) | ||||
| 			if !madeDir[dir] { | ||||
| 				if err := os.MkdirAll(filepath.Dir(abs), 0755); err != nil { | ||||
| 				if err := os.MkdirAll(filepath.Dir(abs), 0o755); err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 				madeDir[dir] = true | ||||
| @@ -321,7 +317,7 @@ func untar(r io.Reader, dir string, level int) (err error) { | ||||
| 				return fmt.Errorf("only wrote %d bytes to %s; expected %d", n, abs, f.Size) | ||||
| 			} | ||||
| 		case mode.IsDir(): | ||||
| 			if err := os.MkdirAll(abs, 0755); err != nil { | ||||
| 			if err := os.MkdirAll(abs, 0o755); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			madeDir[abs] = true | ||||
| @@ -367,14 +363,24 @@ func Copy(src, dst string) (int64, error) { | ||||
| 	return Files{}.Copy(src, dst) | ||||
| } | ||||
| 
 | ||||
| // FileRead is a wrapper for ioutil.ReadFile(). | ||||
| // FileRead is a wrapper for os.ReadFile(). | ||||
| func (f Files) FileRead(path string) ([]byte, error) { | ||||
| 	return ioutil.ReadFile(path) | ||||
| 	return os.ReadFile(path) | ||||
| } | ||||
| 
 | ||||
| // FileWrite is a wrapper for ioutil.WriteFile(). | ||||
| // ReadFile is a wrapper for os.ReadFile() using the same name and syntax. | ||||
| func (f Files) ReadFile(path string) ([]byte, error) { | ||||
| 	return f.FileRead(path) | ||||
| } | ||||
| 
 | ||||
| // FileWrite is a wrapper for os.WriteFile(). | ||||
| func (f Files) FileWrite(path string, content []byte, perm os.FileMode) error { | ||||
| 	return ioutil.WriteFile(path, content, perm) | ||||
| 	return os.WriteFile(path, content, perm) | ||||
| } | ||||
| 
 | ||||
| // WriteFile is a wrapper for os.ReadFile() using the same name and syntax. | ||||
| func (f Files) WriteFile(path string, content []byte, perm os.FileMode) error { | ||||
| 	return f.FileWrite(path, content, perm) | ||||
| } | ||||
| 
 | ||||
| // FileRemove is a wrapper for os.Remove(). | ||||
| @@ -3,9 +3,10 @@ package piperutils | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
|  | ||||
| 	"github.com/SAP/jenkins-library/pkg/log" | ||||
| 	"github.com/SAP/jenkins-library/pkg/piperenv" | ||||
| ) | ||||
|  | ||||
| // Path - struct to serialize paths and some metadata back to the invoker | ||||
| @@ -16,8 +17,12 @@ type Path struct { | ||||
| 	Scope     string `json:"scope"` | ||||
| } | ||||
|  | ||||
| type fileWriter interface { | ||||
| 	WriteFile(filename string, data []byte, perm os.FileMode) error | ||||
| } | ||||
|  | ||||
| // PersistReportsAndLinks stores the report paths and links in JSON format in the workspace for processing outside | ||||
| func PersistReportsAndLinks(stepName, workspace string, reports, links []Path) { | ||||
| func PersistReportsAndLinks(stepName, workspace string, files fileWriter, reports, links []Path) error { | ||||
| 	if reports == nil { | ||||
| 		reports = []Path{} | ||||
| 	} | ||||
| @@ -32,19 +37,25 @@ func PersistReportsAndLinks(stepName, workspace string, reports, links []Path) { | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	reportList, err := json.Marshal(&reports) | ||||
| 	if err != nil { | ||||
| 		if hasMandatoryReport { | ||||
| 			log.Entry().Fatalln("Failed to marshall reports.json data for archiving") | ||||
| 			return fmt.Errorf("failed to marshall reports.json data for archiving: %w", err) | ||||
| 		} | ||||
| 		log.Entry().Errorln("Failed to marshall reports.json data for archiving") | ||||
| 	} | ||||
| 	piperenv.SetParameter(workspace, fmt.Sprintf("%v_reports.json", stepName), string(reportList)) | ||||
|  | ||||
| 	if err := files.WriteFile(filepath.Join(workspace, fmt.Sprintf("%v_reports.json", stepName)), reportList, 0666); err != nil { | ||||
| 		return fmt.Errorf("failed to write reports.json: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	linkList, err := json.Marshal(&links) | ||||
| 	if err != nil { | ||||
| 		log.Entry().Errorln("Failed to marshall links.json data for archiving") | ||||
| 	} else { | ||||
| 		piperenv.SetParameter(workspace, fmt.Sprintf("%v_links.json", stepName), string(linkList)) | ||||
| 		return fmt.Errorf("failed to marshall links.json data for archiving: %w", err) | ||||
| 	} | ||||
| 	if err := files.WriteFile(filepath.Join(workspace, fmt.Sprintf("%v_links.json", stepName)), linkList, 0666); err != nil { | ||||
| 		return fmt.Errorf("failed to write links.json: %w", err) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|   | ||||
| @@ -2,7 +2,8 @@ package piperutils | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"io/ioutil" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"testing" | ||||
|  | ||||
| @@ -10,33 +11,56 @@ import ( | ||||
| 	"github.com/stretchr/testify/require" | ||||
| ) | ||||
|  | ||||
| type fileMock struct { | ||||
| 	fileMap     map[string][]byte | ||||
| 	writeErrors map[string]error | ||||
| } | ||||
|  | ||||
| func (f *fileMock) WriteFile(filename string, data []byte, perm os.FileMode) error { | ||||
| 	if f.writeErrors != nil && f.writeErrors[filename] != nil { | ||||
| 		return f.writeErrors[filename] | ||||
| 	} | ||||
| 	f.fileMap[filename] = data | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (f *fileMock) ReadFile(name string) ([]byte, error) { | ||||
| 	return f.fileMap[name], nil | ||||
| } | ||||
|  | ||||
| func (f *fileMock) FileExists(name string) bool { | ||||
| 	return f.fileMap[name] != nil | ||||
| } | ||||
|  | ||||
| func TestPersistReportAndLinks(t *testing.T) { | ||||
| 	t.Run("default", func(t *testing.T) { | ||||
| 		workspace := t.TempDir() | ||||
| 	workspace := "" | ||||
| 	t.Run("success - default", func(t *testing.T) { | ||||
| 		files := fileMock{fileMap: map[string][]byte{}} | ||||
|  | ||||
| 		reports := []Path{{Target: "testFile1.json", Mandatory: true}, {Target: "testFile2.json"}} | ||||
| 		links := []Path{{Target: "https://1234568.com/test", Name: "Weblink"}} | ||||
| 		PersistReportsAndLinks("checkmarxExecuteScan", workspace, reports, links) | ||||
| 		err := PersistReportsAndLinks("checkmarxExecuteScan", workspace, &files, reports, links) | ||||
| 		assert.NoError(t, err) | ||||
|  | ||||
| 		reportsJSONPath := filepath.Join(workspace, "checkmarxExecuteScan_reports.json") | ||||
| 		assert.FileExists(t, reportsJSONPath) | ||||
| 		assert.True(t, files.FileExists(reportsJSONPath)) | ||||
|  | ||||
| 		linksJSONPath := filepath.Join(workspace, "checkmarxExecuteScan_links.json") | ||||
| 		assert.FileExists(t, linksJSONPath) | ||||
| 		assert.True(t, files.FileExists(linksJSONPath)) | ||||
|  | ||||
| 		var reportsLoaded []Path | ||||
| 		var linksLoaded []Path | ||||
| 		reportsFileData, err := ioutil.ReadFile(reportsJSONPath) | ||||
| 		reportsFileData, err := files.ReadFile(reportsJSONPath) | ||||
| 		reportsDataString := string(reportsFileData) | ||||
| 		println(reportsDataString) | ||||
| 		assert.NoError(t, err, "No error expected but got one") | ||||
|  | ||||
| 		linksFileData, err := ioutil.ReadFile(linksJSONPath) | ||||
| 		linksFileData, err := files.ReadFile(linksJSONPath) | ||||
| 		linksDataString := string(linksFileData) | ||||
| 		println(linksDataString) | ||||
| 		assert.NoError(t, err, "No error expected but got one") | ||||
| 		json.Unmarshal(reportsFileData, &reportsLoaded) | ||||
| 		json.Unmarshal(linksFileData, &linksLoaded) | ||||
| 		_ = json.Unmarshal(reportsFileData, &reportsLoaded) | ||||
| 		_ = json.Unmarshal(linksFileData, &linksLoaded) | ||||
|  | ||||
| 		assert.Equal(t, 2, len(reportsLoaded), "wrong number of reports") | ||||
| 		assert.Equal(t, 1, len(linksLoaded), "wrong number of links") | ||||
| @@ -49,9 +73,8 @@ func TestPersistReportAndLinks(t *testing.T) { | ||||
| 		assert.Equal(t, "Weblink", linksLoaded[0].Name, "name value on link 1 has wrong value") | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("empty list", func(t *testing.T) { | ||||
| 		// init | ||||
| 		workspace := t.TempDir() | ||||
| 	t.Run("success - empty list", func(t *testing.T) { | ||||
| 		files := fileMock{fileMap: map[string][]byte{}} | ||||
|  | ||||
| 		reportsJSONPath := filepath.Join(workspace, "sonarExecuteScan_reports.json") | ||||
| 		linksJSONPath := filepath.Join(workspace, "sonarExecuteScan_links.json") | ||||
| @@ -62,13 +85,42 @@ func TestPersistReportAndLinks(t *testing.T) { | ||||
| 		require.Empty(t, links) | ||||
|  | ||||
| 		// test | ||||
| 		PersistReportsAndLinks("sonarExecuteScan", workspace, reports, links) | ||||
| 		err := PersistReportsAndLinks("sonarExecuteScan", workspace, &files, reports, links) | ||||
| 		// assert | ||||
| 		assert.NoError(t, err) | ||||
| 		for _, reportFile := range []string{reportsJSONPath, linksJSONPath} { | ||||
| 			assert.FileExists(t, reportFile) | ||||
| 			reportsFileData, err := ioutil.ReadFile(reportFile) | ||||
| 			assert.True(t, files.FileExists(reportFile)) | ||||
| 			reportsFileData, err := files.ReadFile(reportFile) | ||||
| 			require.NoError(t, err, "No error expected but got one") | ||||
| 			assert.Equal(t, "[]", string(reportsFileData)) | ||||
| 		} | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("failure - write reports", func(t *testing.T) { | ||||
| 		stepName := "checkmarxExecuteScan" | ||||
| 		files := fileMock{ | ||||
| 			fileMap:     map[string][]byte{}, | ||||
| 			writeErrors: map[string]error{filepath.Join(workspace, fmt.Sprintf("%v_reports.json", stepName)): fmt.Errorf("write error")}, | ||||
| 		} | ||||
|  | ||||
| 		reports := []Path{{Target: "testFile1.json"}, {Target: "testFile2.json"}} | ||||
| 		links := []Path{{Target: "https://1234568.com/test", Name: "Weblink"}} | ||||
| 		err := PersistReportsAndLinks(stepName, workspace, &files, reports, links) | ||||
|  | ||||
| 		assert.EqualError(t, err, "failed to write reports.json: write error") | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("failure - write links", func(t *testing.T) { | ||||
| 		stepName := "checkmarxExecuteScan" | ||||
| 		files := fileMock{ | ||||
| 			fileMap:     map[string][]byte{}, | ||||
| 			writeErrors: map[string]error{filepath.Join(workspace, fmt.Sprintf("%v_links.json", stepName)): fmt.Errorf("write error")}, | ||||
| 		} | ||||
|  | ||||
| 		reports := []Path{{Target: "testFile1.json"}, {Target: "testFile2.json"}} | ||||
| 		links := []Path{{Target: "https://1234568.com/test", Name: "Weblink"}} | ||||
| 		err := PersistReportsAndLinks(stepName, workspace, &files, reports, links) | ||||
|  | ||||
| 		assert.EqualError(t, err, "failed to write links.json: write error") | ||||
| 	}) | ||||
| } | ||||
|   | ||||
| @@ -4,7 +4,7 @@ import ( | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| 	"io/fs" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"time" | ||||
| @@ -31,6 +31,8 @@ type Toolrecord struct { | ||||
| 	DisplayName string | ||||
| 	DisplayURL  string | ||||
| 
 | ||||
| 	fileUtils fileWriteUtils | ||||
| 
 | ||||
| 	// detailed keydata - needs tool-specific parsing | ||||
| 	Keys []keydataset | ||||
| 
 | ||||
| @@ -42,9 +44,15 @@ type Toolrecord struct { | ||||
| 	reportFileName string | ||||
| } | ||||
| 
 | ||||
| type fileWriteUtils interface { | ||||
| 	MkdirAll(path string, perm fs.FileMode) error | ||||
| 	WriteFile(name string, data []byte, perm fs.FileMode) error | ||||
| } | ||||
| 
 | ||||
| // New - initialize a new toolrecord | ||||
| func New(workspace, toolName, toolInstance string) *Toolrecord { | ||||
| func New(fileUtils fileWriteUtils, workspace, toolName, toolInstance string) *Toolrecord { | ||||
| 	tr := Toolrecord{} | ||||
| 	tr.fileUtils = fileUtils | ||||
| 
 | ||||
| 	tr.RecordVersion = 1 | ||||
| 	tr.ToolName = toolName | ||||
| @@ -108,7 +116,7 @@ func (tr *Toolrecord) Persist() error { | ||||
| 	} | ||||
| 	// create workspace/toolrecord | ||||
| 	dirPath := filepath.Join(tr.workspace, "toolruns") | ||||
| 	err := os.MkdirAll(dirPath, os.ModePerm) | ||||
| 	err := tr.fileUtils.MkdirAll(dirPath, os.ModePerm) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("TR_PERSIST: %v", err) | ||||
| 	} | ||||
| @@ -126,14 +134,14 @@ func (tr *Toolrecord) Persist() error { | ||||
| 	if len(file) == 0 { | ||||
| 		return fmt.Errorf("TR_PERSIST: empty json content") | ||||
| 	} | ||||
| 	err = ioutil.WriteFile(tr.GetFileName(), file, 0644) | ||||
| 	err = tr.fileUtils.WriteFile(tr.GetFileName(), file, 0o644) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("TR_PERSIST: %v", err) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // default aggregation for overall displayName and URL | ||||
| // GenerateDefaultDisplayData - default aggregation for overall displayName and URL | ||||
| // can be overriden by calling SetOverallDisplayData | ||||
| func (tr *Toolrecord) GenerateDefaultDisplayData() { | ||||
| 	displayName := "" | ||||
| @@ -156,7 +164,7 @@ func (tr *Toolrecord) GenerateDefaultDisplayData() { | ||||
| 	tr.DisplayURL = displayURL | ||||
| } | ||||
| 
 | ||||
| // Override the default generation for DisplayName & DisplayURL | ||||
| // SetOverallDisplayData - override the default generation for DisplayName & DisplayURL | ||||
| func (tr *Toolrecord) SetOverallDisplayData(newName, newURL string) { | ||||
| 	tr.DisplayName = newName | ||||
| 	tr.DisplayURL = newURL | ||||
| @@ -3,6 +3,7 @@ package toolrecord_test | ||||
| import ( | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/SAP/jenkins-library/pkg/mock" | ||||
| 	"github.com/SAP/jenkins-library/pkg/toolrecord" | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| ) | ||||
| @@ -11,11 +12,12 @@ func TestToolRecord(t *testing.T) { | ||||
| 	workspace := t.TempDir() | ||||
|  | ||||
| 	t.Run("Check toolrecord", func(t *testing.T) { | ||||
| 		tr := toolrecord.New(workspace, "dummyTool", "dummyInstance") | ||||
| 		fileMock := mock.FilesMock{} | ||||
| 		tr := toolrecord.New(&fileMock, workspace, "dummyTool", "dummyInstance") | ||||
|  | ||||
| 		tr.AddKeyData("Organization", "dummyOrgId", "dummyOrgName", "dummyOrgUrl") | ||||
| 		tr.AddKeyData("Project", "dummyProjectId", "dummyProjName", "dummyProjUrl") | ||||
| 		tr.AddKeyData("ScanId", "dummyScanId", "dummyScanName", "dummyScanUrl") | ||||
| 		_ = tr.AddKeyData("Organization", "dummyOrgId", "dummyOrgName", "dummyOrgUrl") | ||||
| 		_ = tr.AddKeyData("Project", "dummyProjectId", "dummyProjName", "dummyProjUrl") | ||||
| 		_ = tr.AddKeyData("ScanId", "dummyScanId", "dummyScanName", "dummyScanUrl") | ||||
| 		context := map[string]interface{}{ | ||||
| 			"demo": "data", | ||||
| 			"anything": struct { | ||||
| @@ -23,15 +25,15 @@ func TestToolRecord(t *testing.T) { | ||||
| 				i1 int | ||||
| 			}{"goes", 42}, | ||||
| 		} | ||||
| 		tr.AddContext("DemoContext", context) | ||||
| 		_ = tr.AddContext("DemoContext", context) | ||||
| 		context2 := "a string" | ||||
| 		tr.AddContext("Context2", context2) | ||||
| 		_ = tr.AddContext("Context2", context2) | ||||
| 		var context3 [2]string | ||||
| 		context3[0] = "c3_1" | ||||
| 		context3[1] = "c3_2" | ||||
| 		tr.AddContext("Context3", context3) | ||||
| 		_ = tr.AddContext("Context3", context3) | ||||
| 		err := tr.Persist() | ||||
| 		assert.Nil(t, err, "internal error %s") | ||||
| 		assert.FileExists(t, tr.GetFileName(), "toolrecord not persisted %s") | ||||
| 		assert.True(t, fileMock.HasFile(tr.GetFileName()), "toolrecord not persisted %s") | ||||
| 	}) | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user