1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2024-12-14 11:03:09 +02:00
sap-jenkins-library/test/groovy/CommonStepsTest.groovy

287 lines
12 KiB
Groovy
Raw Normal View History

import static java.util.stream.Collectors.toList
import static org.hamcrest.Matchers.empty
import static org.hamcrest.Matchers.equalTo
import static org.hamcrest.Matchers.is
import static org.junit.Assert.assertThat
import static org.junit.Assert.fail
import static util.StepHelper.getSteps
2019-05-22 16:56:50 +02:00
import java.io.File
import java.util.stream.Collectors
import java.lang.reflect.Field
import org.codehaus.groovy.runtime.metaclass.MethodSelectionException
import org.hamcrest.Matchers
import org.junit.Assert
import org.junit.Rule
import org.junit.Test
import org.junit.rules.ExpectedException
import org.junit.rules.RuleChain
import groovy.io.FileType
import hudson.AbortException
import util.BasePiperTest
import util.JenkinsReadYamlRule
import util.JenkinsStepRule
import util.Rules
/*
* Intended for collecting generic checks applied to all steps.
*/
public class CommonStepsTest extends BasePiperTest{
@Rule
public RuleChain ruleChain = Rules.getCommonRules(this)
.around(new JenkinsReadYamlRule(this))
/*
* With that test we ensure the very first action inside a method body of a call method
* for a not white listed step is the check for the script handed over properly.
* Actually we assert for the exception type (AbortException) and for the exception message.
* In case a new step is added this step will fail. It is the duty of the author of the
* step to either follow the pattern of checking the script first or to add the step
* to the white list.
*/
@Test
public void scriptReferenceNotHandedOverTest() {
// all steps not adopting the usual pattern of working with the script.
def whitelistScriptReference = [
2020-06-23 15:56:56 +02:00
'abapEnvironmentPipeline',
'buildSetResult',
'commonPipelineEnvironment',
'handlePipelineStepErrors',
'pipelineExecute',
'piperExecuteBin',
2020-06-23 15:56:56 +02:00
'piperPipeline',
'prepareDefaultValues',
'runClosures',
2020-06-23 15:56:56 +02:00
'setupCommonPipelineEnvironment'
]
List steps = getSteps().stream()
.filter {! whitelistScriptReference.contains(it)}
.forEach {checkReference(it)}
}
private void checkReference(step) {
try {
def script = loadScript("${step}.groovy")
try {
System.setProperty('com.sap.piper.featureFlag.failOnMissingScript', 'true')
try {
script.call([:])
} catch(AbortException | MissingMethodException e) {
throw e
} catch(Exception e) {
fail "Unexpected exception ${e.getClass().getName()} caught from step '${step}': ${e.getMessage()}"
}
fail("Expected AbortException not raised by step '${step}'")
} catch(MissingMethodException e) {
// can be improved: exception handling as some kind of control flow.
// we can also check for the methods and call the appropriate one.
try {
script.call([:]) {}
} catch(AbortException e1) {
throw e1
} catch(Exception e1) {
fail "Unexpected exception ${e1.getClass().getName()} caught from step '${step}': ${e1.getMessage()}"
}
fail("Expected AbortException not raised by step '${step}'")
}
} catch(AbortException e) {
assertThat("Step ''${step} does not fail with expected error message in case mandatory parameter 'script' is not provided.",
e.getMessage() ==~ /.*\[ERROR\]\[.*\] No reference to surrounding script provided with key 'script', e.g. 'script: this'./,
is(equalTo(true)))
} finally {
System.clearProperty('com.sap.piper.featureFlag.failOnMissingScript')
}
}
private static fieldRelatedWhitelist = [
2020-06-23 15:56:56 +02:00
'abapEnvironmentPipeline', // special step (infrasturcture)
'artifactPrepareVersion',
'durationMeasure', // only expects parameters via signature
'prepareDefaultValues', // special step (infrastructure)
'piperPipeline', // special step (infrastructure)
'pipelineStashFilesAfterBuild', // intended to be called from pipelineStashFiles
'pipelineStashFilesBeforeBuild', // intended to be called from pipelineStashFiles
'pipelineStashFiles', // only forwards to before/after step
'pipelineExecute', // special step (infrastructure)
'commonPipelineEnvironment', // special step (infrastructure)
'handlePipelineStepErrors', // special step (infrastructure)
'piperStageWrapper', //intended to be called from within stages
'buildSetResult',
'runClosures',
'abapEnvironmentPullGitRepo', //implementing new golang pattern without fields
'checkmarxExecuteScan', //implementing new golang pattern without fields
2019-12-13 17:05:55 +02:00
'githubPublishRelease', //implementing new golang pattern without fields
'kubernetesDeploy', //implementing new golang pattern without fields
'piperExecuteBin', //implementing new golang pattern without fields
'protecodeExecuteScan', //implementing new golang pattern without fields
2019-12-13 17:05:55 +02:00
'xsDeploy', //implementing new golang pattern without fields
'cloudFoundryDeleteService', //implementing new golang pattern without fields
'cloudFoundryCreateServiceKey', //implementing new golang pattern without fields
'npmExecuteScripts', //implementing new golang pattern without fields
'npmExecuteLint', //implementing new golang pattern without fields
'malwareExecuteScan', //implementing new golang pattern without fields
2020-03-23 10:58:54 +02:00
'mavenBuild', //implementing new golang pattern without fields
'mavenExecute', //implementing new golang pattern without fields
'mavenExecuteIntegration', //implementing new golang pattern without fields
2020-03-23 10:58:54 +02:00
'mavenExecuteStaticCodeChecks', //implementing new golang pattern without fields
'mtaBuild', //implementing new golang pattern without fields
'nexusUpload', //implementing new golang pattern without fields
'piperPipelineStageArtifactDeployment', //stage without step flags
Add abapEnvironmentRunATCCheck step (#1454) * Minor changes * Changed groovy file * Changed generated file * Changed yaml with container config * Changed groovy config * minor changes * minor changes * Changed yaml with aliases * minor changes * minor changes * minor changes * minor changes * minor changes * minor changes * minor changes * minor changes * minor changes * minor changes * Changed yaml aliases * Adapted naming conventions * Removed error code at the end * Adapted configuration * Minor changes * Minor changes * Minor changes * Removed spaces * Removed docker-related config from groovy file * Minor changes * Minor changes * Removed container config * Corrected testing function name * Deleted unnecessary parts * Changed service deletion message * Changed service deletion message * Logging out before throwing error service deletion step fails * Minor changes * Minor changes * Minor changes * Delete .DS_Store * Delete .DS_Store * Delete .DS_Store * Delete .DS_Store * Minor changes * Minor changes * Minor changes * Added newline at end of file * Added newline at end of file * Changes for Pull request optimization * added documentaion * Adapted documentation * Adapted documentation * Adapted documentation * Adapted documentation * Adapted documentation * Added CFDeleteServiceKeys * Added ServiceKey deletion tests * added cfServiceKeys flag explanation to documentation * removed trailing spaces from documentation * resolving conflicts * Changed deletion message an variable naming * Changed tests * Changed tests * Changed tests * Changed tests * Changed CloudFoundryDeleteServiceOptions to options * Changed CloudFoundryDeleteServiceOptions to options * Minor changes * Minor changes * Changed variable naming * Changed error handling * Changed error handling and logging * Changed documentation * Simplified code * Fixed CodeClimate issues * Changed from returning err to nil where no errur returned needed * Add cloudFoundryCreateServiceKey Go Step * Changed Groovy File * Changed aliases * Removed unneccessary parts * Minor changes * Minor changes * Adapted documentation * Adapted tests * Adapted Groovy File * Changed Groovy file * Minor changes * Minor changes * Minor changes * Minor changes * Minor changes * Minor changes * Minor changes * Minor changes * Minor changes * Minor changes * Minor changes * Minor changes * Minor changes * Minor changes * Minor changes * Minor changes * Minor changes * Minor changes * Minor changes * Minor changes * Removed Groovy Tests for cfCreateServiceKey * Minor changes * Added ATC Check YAML * Added ATC Check generated files * Added test class * Added abapEnvironmentRunATCCheck * Minor changes * Minor changes * Changed groovy * Minor changes * Changed groovy * Changed groovy * Minor changes * Adapted Groovy imports * Adapted Groovy imports * Adapted Groovy imports * Adapted Groovy * Getting ATC results * Changed error message * changed groovy * removed trailing spaces * Added login check * Minor changes * Added step to whitelistScriptReference * Added ATC error message handling * Added groovy file * Added step to groovy tests * corrected metadata file * Debugging * Debugging * Added yaml config parameter for ATC run * Adapted file location of ATC run config to jenkins specific location * Implementing universal pipeline logic for finding yaml config regardless of pipeline * Changed error handling for reading config yaml file * Changed atcrunconfig alias * minor changes * Minor changes * Minor changes * Changed back to dynamic file reading * Minor changes * filepath changes * Removing CF Login * Minor changes * Minor changes * Minor changes * Minor changes * Minor changes * Minor changes * Removed whitespaces * Added CF functions unit tests * Added invalid parameter handling * Removed package and SC flag * Minor changes * Changed tests * Changed tests * Changed tests * Minor changes * Changed tests * removed unnecessary logout * Added documentation * Changed docu * Changed docu * Changed docu * Changed docu * Changed docu * Changed docu * Changed docu * Changed docu * Changed docu * Changed docu * Removed trailing spaces * Added newline at end of file * code climate fixes * code climate fixes * code climate fixes * Minor changes * Minor changes * Minor changes * Changed tests * Test changes * Splitted Cloud Foundry functions into two classes * Removed two steps from whtielistScriptReference * removed atcrunConfig alias * issue fixes * Changed docu * Changed docu * Changed docu * Removed trailing spaced from docu * Changed docu * Go generator run * Issue fixes * Remove unnecessary imports Co-authored-by: Christopher Fenner <26137398+CCFenner@users.noreply.github.com> * Update whitelistScript Co-authored-by: Christopher Fenner <26137398+CCFenner@users.noreply.github.com> * Adding piperutils for writing xml file * Persisting ATC Results with piperutils * Set failonMissingReports to true * Refactoring for CodeClimate * Changed result file name * Changed credentials aliases * changing secret name * Removing trailing spaces * Added secret name and alias to docu Co-authored-by: Oliver Nocon <33484802+OliverNocon@users.noreply.github.com> Co-authored-by: Christopher Fenner <26137398+CCFenner@users.noreply.github.com>
2020-05-13 14:51:48 +02:00
'abapEnvironmentRunATCCheck', //implementing new golang pattern without fields
'sonarExecuteScan', //implementing new golang pattern without fields
'gctsCreateRepository', //implementing new golang pattern without fields
'gctsRollback', //implementing new golang pattern without fields
'gctsExecuteABAPUnitTests', //implementing new golang pattern without fields
'gctsCloneRepository', //implementing new golang pattern without fields
'fortifyExecuteScan', //implementing new golang pattern without fields
'gctsDeploy', //implementing new golang pattern without fields
'containerSaveImage', //implementing new golang pattern without fields
'detectExecuteScan', //implementing new golang pattern without fields
'kanikoExecute' //implementing new golang pattern without fields
]
@Test
public void generalConfigKeysSetPresentTest() {
def fieldName = 'GENERAL_CONFIG_KEYS'
// the steps added to the fieldRelatedWhitelist do not take the general config at all
def stepsWithoutGeneralConfigKeySet = fieldCheck(fieldName, fieldRelatedWhitelist.plus(['gaugeExecuteTests',
'pipelineRestartSteps']))
assertThat("Steps without ${fieldName} field (or that field is not a Set): ${stepsWithoutGeneralConfigKeySet}",
stepsWithoutGeneralConfigKeySet, is(empty()))
}
@Test
public void stepConfigKeysSetPresentTest() {
def fieldName = 'STEP_CONFIG_KEYS'
def stepsWithoutStepConfigKeySet = fieldCheck(fieldName, fieldRelatedWhitelist.plus('setupCommonPipelineEnvironment'))
assertThat("Steps without ${fieldName} field (or that field is not a Set): ${stepsWithoutStepConfigKeySet}",
stepsWithoutStepConfigKeySet, is(empty()))
}
@Test
public void parametersKeysSetPresentTest() {
def fieldName = 'PARAMETER_KEYS'
def stepsWithoutParametersKeySet = fieldCheck(fieldName, fieldRelatedWhitelist.plus('setupCommonPipelineEnvironment'))
assertThat("Steps without ${fieldName} field (or that field is not a Set): ${stepsWithoutParametersKeySet}",
stepsWithoutParametersKeySet, is(empty()))
}
private fieldCheck(fieldName, whitelist) {
def stepsWithoutGeneralConfigKeySet = []
for(def step in getSteps()) {
if(whitelist.contains(step)) continue
def fields = loadScript("${step}.groovy").getClass().getDeclaredFields() as Set
Field generalConfigKeyField = fields.find{ it.getName() == fieldName}
if(! generalConfigKeyField ||
! generalConfigKeyField
.getType()
.isAssignableFrom(Set.class)) {
stepsWithoutGeneralConfigKeySet.add(step)
}
}
return stepsWithoutGeneralConfigKeySet
}
@Test
public void stepsWithWrongFieldNameTest() {
def whitelist = [
2020-06-23 15:56:56 +02:00
'abapEnvironmentPipeline',
'commonPipelineEnvironment',
'piperPipeline',
'piperExecuteBin',
'buildSetResult',
'runClosures'
]
def stepsWithWrongStepName = []
for(def step in getSteps()) {
if(whitelist.contains(step)) continue
def script = loadScript("${step}.groovy")
def fields = script.getClass().getDeclaredFields() as Set
Field stepNameField = fields.find { it.getName() == 'STEP_NAME'}
if(! stepNameField) {
stepsWithWrongStepName.add(step)
continue
}
2019-05-22 16:56:50 +02:00
boolean notAccessible = false
def fieldName
if(!stepNameField.isAccessible()) {
stepNameField.setAccessible(true)
notAccessible = true
}
try {
fieldName = stepNameField.get(script)
} finally {
if(notAccessible) stepNameField.setAccessible(false)
}
if(fieldName != step) {
stepsWithWrongStepName.add(step)
}
}
assertThat("Steps with wrong step name or without STEP_NAME field.: ${stepsWithWrongStepName}",
stepsWithWrongStepName, is(empty()))
}
2018-09-25 13:58:38 +02:00
/*
* With that test we ensure that all return types of the call methods of all the steps
* are void. Return types other than void are not possible when running inside declarative
* pipelines. Parameters shared between several steps needs to be shared via the commonPipelineEnvironment.
*/
@Test
public void returnTypeForCallMethodsIsVoidTest() {
def stepsWithCallMethodsOtherThanVoid = []
def whitelist = [
'durationMeasure',
'mavenExecute'
2018-09-25 13:58:38 +02:00
]
for(def step in getSteps()) {
def methods = loadScript("${step}.groovy").getClass().getDeclaredMethods() as List
Collection callMethodsWithReturnTypeOtherThanVoid =
methods.stream()
.filter { ! whitelist.contains(step) }
.filter { it.getName() == 'call' &&
it.getReturnType() != Void.TYPE }
.collect(toList())
if(!callMethodsWithReturnTypeOtherThanVoid.isEmpty()) stepsWithCallMethodsOtherThanVoid << step
}
assertThat("Steps with call methods with return types other than void: ${stepsWithCallMethodsOtherThanVoid}",
stepsWithCallMethodsOtherThanVoid, is(empty()))
}
}