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/PiperExecuteBinTest.groovy

414 lines
16 KiB
Groovy
Raw Normal View History

import com.sap.piper.DebugReport
import com.sap.piper.JenkinsUtils
import groovy.json.JsonSlurper
import hudson.AbortException
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.ExpectedException
import org.junit.rules.RuleChain
import util.*
import static org.hamcrest.Matchers.*
import static org.junit.Assert.assertThat
class PiperExecuteBinTest extends BasePiperTest {
private ExpectedException exception = ExpectedException.none()
private JenkinsCredentialsRule credentialsRule = new JenkinsCredentialsRule(this)
private JenkinsShellCallRule shellCallRule = new JenkinsShellCallRule(this)
private JenkinsStepRule stepRule = new JenkinsStepRule(this)
private JenkinsWriteFileRule writeFileRule = new JenkinsWriteFileRule(this)
private JenkinsFileExistsRule fileExistsRule = new JenkinsFileExistsRule(this, [])
private JenkinsDockerExecuteRule dockerExecuteRule = new JenkinsDockerExecuteRule(this)
private List withEnvArgs = []
private List credentials = []
private List artifacts = []
@Rule
public RuleChain rules = Rules
.getCommonRules(this)
.around(exception)
.around(new JenkinsReadYamlRule(this))
.around(credentialsRule)
.around(shellCallRule)
.around(stepRule)
.around(writeFileRule)
.around(fileExistsRule)
.around(dockerExecuteRule)
@Before
void init() {
credentials = []
// Clear DebugReport to avoid left-overs from another UnitTest
DebugReport.instance.failedBuild = [:]
helper.registerAllowedMethod("withEnv", [List.class, Closure.class], {arguments, closure ->
arguments.each {arg ->
withEnvArgs.add(arg.toString())
}
return closure()
})
helper.registerAllowedMethod("writePipelineEnv", [Map.class], {m -> return })
helper.registerAllowedMethod("readPipelineEnv", [Map.class], {m -> return })
helper.registerAllowedMethod('fileExists', [Map.class], {m ->
if (m.file == 'noDetailsStep_errorDetails.json') {
return false
}
return true
})
helper.registerAllowedMethod("readJSON", [Map], { m ->
if(m.file == 'testStep_reports.json')
return [[target: "1234.pdf", mandatory: true]]
if(m.file == 'testStep_links.json')
return []
if(m.file == 'testStepCategory_errorDetails.json')
return [message: 'detailed error', category: 'testCategory']
if(m.file == 'testStep_errorDetails.json')
return [message: 'detailed error']
if(m.text != null)
return new JsonSlurper().parseText(m.text)
})
helper.registerAllowedMethod('libraryResource', [String.class], {s ->
if (s == 'metadata/test.yaml') {
return '''metadata:
name: testStep
'''
} else {
return '''general:
failOnError: true
'''
}
})
helper.registerAllowedMethod('file', [Map], { m -> return m })
helper.registerAllowedMethod('string', [Map], { m -> return m })
helper.registerAllowedMethod('usernamePassword', [Map], { m -> return m })
helper.registerAllowedMethod('withCredentials', [List, Closure], { l, c ->
l.each {m ->
credentials.add(m)
if (m.credentialsId == 'credFile') {
binding.setProperty('PIPER_credFile', 'credFileContent')
} else if (m.credentialsId == 'credToken') {
binding.setProperty('PIPER_credToken','credTokenContent')
} else if (m.credentialsId == 'credUsernamePassword') {
binding.setProperty('PIPER_user', 'userId')
binding.setProperty('PIPER_password', '********')
}
}
try {
c()
} finally {
binding.setProperty('PIPER_credFile', null)
binding.setProperty('PIPER_credToken', null)
binding.setProperty('PIPER_user', null)
binding.setProperty('PIPER_password', null)
}
})
helper.registerAllowedMethod('archiveArtifacts', [Map.class], {m ->
artifacts.add(m)
return null
})
helper.registerAllowedMethod('findFiles', [Map.class], {m -> return null})
}
@Test
void testPiperExecuteBinDefault() {
shellCallRule.setReturnValue('./piper getConfig --contextConfig --stepMetadata \'.pipeline/tmp/metadata/test.yaml\'', '{"fileCredentialsId":"credFile", "tokenCredentialsId":"credToken", "credentialsId":"credUsernamePassword", "dockerImage":"my.Registry/my/image:latest"}')
List stepCredentials = [
[type: 'file', id: 'fileCredentialsId', env: ['PIPER_credFile']],
[type: 'token', id: 'tokenCredentialsId', env: ['PIPER_credToken']],
[type: 'usernamePassword', id: 'credentialsId', env: ['PIPER_user', 'PIPER_password']],
]
stepRule.step.piperExecuteBin(
[
juStabUtils: utils,
jenkinsUtilsStub: jenkinsUtils,
testParam: "This is test content",
script: nullScript
],
'testStep',
'metadata/test.yaml',
stepCredentials
)
// asserts
assertThat(writeFileRule.files['.pipeline/tmp/metadata/test.yaml'], containsString('name: testStep'))
assertThat(withEnvArgs[0], allOf(startsWith('PIPER_parametersJSON'), containsString('"testParam":"This is test content"')))
assertThat(shellCallRule.shell[1], is('./piper testStep'))
assertThat(credentials.size(), is(3))
assertThat(credentials[0], allOf(hasEntry('credentialsId', 'credFile'), hasEntry('variable', 'PIPER_credFile')))
assertThat(credentials[1], allOf(hasEntry('credentialsId', 'credToken'), hasEntry('variable', 'PIPER_credToken')))
assertThat(credentials[2], allOf(hasEntry('credentialsId', 'credUsernamePassword'), hasEntry('usernameVariable', 'PIPER_user') , hasEntry('passwordVariable', 'PIPER_password')))
assertThat(dockerExecuteRule.dockerParams.dockerImage, is('my.Registry/my/image:latest'))
assertThat(dockerExecuteRule.dockerParams.stashContent, is([]))
assertThat(artifacts[0], allOf(hasEntry('artifacts', '1234.pdf'), hasEntry('allowEmptyArchive', false)))
}
@Test
void testPiperExecuteBinDontResolveCredentialsAndNoCredId() {
// In case we have a credential entry without Id we drop that silenty.
// Maybe we should revisit that and fail in this case.
shellCallRule.setReturnValue('./piper getConfig --contextConfig --stepMetadata \'.pipeline/tmp/metadata/test.yaml\'', '{"dockerImage":"my.Registry/my/image:latest"}')
List stepCredentials = [
[type: 'token', env: ['PIPER_credTokenNoResolve'], resolveCredentialsId: false],
]
stepRule.step.piperExecuteBin(
[
juStabUtils: utils,
jenkinsUtilsStub: jenkinsUtils,
testParam: "This is test content",
script: nullScript
],
'testStep',
'metadata/test.yaml',
stepCredentials
)
assertThat(credentials.size(), is(0))
}
@Test
void testPiperExecuteBinSomeCredentials() {
shellCallRule.setReturnValue('./piper getConfig --contextConfig --stepMetadata \'.pipeline/tmp/metadata/test.yaml\'', '{"fileCredentialsId":"credFile", "tokenCredentialsId":"credToken", "dockerImage":"my.Registry/my/image:latest"}')
List stepCredentials = [
[type: 'file', id: 'fileCredentialsId', env: ['PIPER_credFile']],
[type: 'token', id: 'tokenCredentialsId', env: ['PIPER_credToken']],
// for the entry below we don't have a config lookup.
[type: 'token', id: 'tokenCredentialsIdNoResolve', env: ['PIPER_credTokenNoResolve'], resolveCredentialsId: false],
[type: 'token', id: 'tokenCredentialsIdNotContainedInConfig', env: ['PIPER_credToken_doesNotMatter']],
[type: 'usernamePassword', id: 'credentialsId', env: ['PIPER_user', 'PIPER_password']],
]
stepRule.step.piperExecuteBin(
[
juStabUtils: utils,
jenkinsUtilsStub: jenkinsUtils,
testParam: "This is test content",
script: nullScript
],
'testStep',
'metadata/test.yaml',
stepCredentials
)
// asserts
assertThat(credentials.size(), is(3))
assertThat(credentials[0], allOf(hasEntry('credentialsId', 'credFile'), hasEntry('variable', 'PIPER_credFile')))
assertThat(credentials[1], allOf(hasEntry('credentialsId', 'credToken'), hasEntry('variable', 'PIPER_credToken')))
assertThat(credentials[2], allOf(hasEntry('credentialsId', 'tokenCredentialsIdNoResolve'), hasEntry('variable', 'PIPER_credTokenNoResolve')))
}
@Test
void testPiperExecuteBinSSHCredentials() {
shellCallRule.setReturnValue('./piper getConfig --contextConfig --stepMetadata \'.pipeline/tmp/metadata/test.yaml\'', '{"sshCredentialsId":"sshKey", "tokenCredentialsId":"credToken"}')
List sshKey = []
helper.registerAllowedMethod("sshagent", [List, Closure], {s, c ->
sshKey = s
c()
})
List stepCredentials = [
[type: 'token', id: 'tokenCredentialsId', env: ['PIPER_credToken']],
[type: 'ssh', id: 'sshCredentialsId'],
]
stepRule.step.piperExecuteBin(
[
juStabUtils: utils,
jenkinsUtilsStub: jenkinsUtils,
testParam: "This is test content",
script: nullScript
],
'testStep',
'metadata/test.yaml',
stepCredentials
)
// asserts
assertThat(credentials.size(), is(1))
assertThat(credentials[0], allOf(hasEntry('credentialsId', 'credToken'), hasEntry('variable', 'PIPER_credToken')))
assertThat(sshKey, is(['sshKey']))
}
@Test
void testPiperExecuteBinNoDockerNoCredentials() {
shellCallRule.setReturnValue('./piper getConfig --contextConfig --stepMetadata \'.pipeline/tmp/metadata/test.yaml\'', '{}')
stepRule.step.piperExecuteBin(
[
juStabUtils: utils,
jenkinsUtilsStub: jenkinsUtils,
testParam: "This is test content",
script: nullScript
],
'testStep',
'metadata/test.yaml',
[]
)
assertThat(writeFileRule.files['.pipeline/tmp/metadata/test.yaml'], containsString('name: testStep'))
assertThat(withEnvArgs[0], allOf(startsWith('PIPER_parametersJSON'), containsString('"testParam":"This is test content"')))
assertThat(shellCallRule.shell[1], is('./piper testStep'))
assertThat(credentials.size(), is(0))
assertThat(dockerExecuteRule.dockerParams.size(), is(0))
assertThat(artifacts[0], allOf(hasEntry('artifacts', '1234.pdf'), hasEntry('allowEmptyArchive', false)))
}
@Test
void testPiperExecuteBinNoReportFound() {
shellCallRule.setReturnValue('./piper getConfig --contextConfig --stepMetadata \'.pipeline/tmp/metadata/test.yaml\'', '{}')
helper.registerAllowedMethod('fileExists', [Map], {
return false
})
exception.expect(AbortException)
exception.expectMessage("Expected to find testStep_reports.json in workspace but it is not there")
stepRule.step.piperExecuteBin(
[
juStabUtils: utils,
jenkinsUtilsStub: jenkinsUtils,
testParam: "This is test content",
script: nullScript
],
'testStep',
'metadata/test.yaml',
[],
true,
false,
false
)
}
@Test
void testErrorWithCategory() {
shellCallRule.setReturnValue('./piper getConfig --contextConfig --stepMetadata \'.pipeline/tmp/metadata/test.yaml\'', '{}')
helper.registerAllowedMethod('sh', [String.class], {s -> throw new AbortException('exit code 1')})
exception.expect(AbortException)
exception.expectMessage("[testStepCategory] Step execution failed (category: testCategory). Error: detailed error")
try {
stepRule.step.piperExecuteBin(
[
juStabUtils: utils,
jenkinsUtilsStub: jenkinsUtils,
testParam: "This is test content",
script: nullScript
],
'testStepCategory',
'metadata/test.yaml',
[]
)
} catch (ex) {
assertThat(DebugReport.instance.failedBuild.category, is('testCategory'))
throw ex
}
}
@Test
void testErrorWithoutCategory() {
shellCallRule.setReturnValue('./piper getConfig --contextConfig --stepMetadata \'.pipeline/tmp/metadata/test.yaml\'', '{}')
helper.registerAllowedMethod('sh', [String.class], {s -> throw new AbortException('exit code 1')})
exception.expect(AbortException)
exception.expectMessage("[testStep] Step execution failed. Error: detailed error")
stepRule.step.piperExecuteBin(
[
juStabUtils: utils,
jenkinsUtilsStub: jenkinsUtils,
testParam: "This is test content",
script: nullScript
],
'testStep',
'metadata/test.yaml',
[]
)
}
@Test
void testErrorNoDetails() {
shellCallRule.setReturnValue('./piper getConfig --contextConfig --stepMetadata \'.pipeline/tmp/metadata/test.yaml\'', '{}')
helper.registerAllowedMethod('sh', [String.class], {s -> throw new AbortException('exit code 1')})
exception.expect(AbortException)
exception.expectMessage("[noDetailsStep] Step execution failed. Error: hudson.AbortException: exit code 1, please see log file for more details.")
stepRule.step.piperExecuteBin(
[
juStabUtils: utils,
jenkinsUtilsStub: jenkinsUtils,
testParam: "This is test content",
script: nullScript
],
'noDetailsStep',
'metadata/test.yaml',
[]
)
}
@Test
void testRespectPipelineResilienceSetting() {
shellCallRule.setReturnValue('./piper getConfig --contextConfig --stepMetadata \'.pipeline/tmp/metadata/test.yaml\'', '{}')
helper.registerAllowedMethod('sh', [String.class], {s -> throw new AbortException('exit code 1')})
def unstableCalled
helper.registerAllowedMethod('unstable', [String.class], {s -> unstableCalled = true})
try {
nullScript.commonPipelineEnvironment.configuration.steps = [handlePipelineStepErrors: [failOnError: false]]
stepRule.step.piperExecuteBin(
[
juStabUtils: utils,
jenkinsUtilsStub: jenkinsUtils,
testParam: "This is test content",
script: nullScript
],
'noDetailsStep',
'metadata/test.yaml',
[]
)
} finally {
//clean up
nullScript.commonPipelineEnvironment.configuration.steps = [handlePipelineStepErrors: [failOnError: true]]
}
assertThat(unstableCalled, is(true))
}
@Test
void testProperStashHandling() {
shellCallRule.setReturnValue('./piper getConfig --contextConfig --stepMetadata \'.pipeline/tmp/metadata/test.yaml\'', '{"dockerImage":"test","stashContent":["buildDescriptor"]}')
stepRule.step.piperExecuteBin(
[
juStabUtils: utils,
jenkinsUtilsStub: jenkinsUtils,
script: nullScript
],
'testStep',
'metadata/test.yaml',
[]
)
assertThat(dockerExecuteRule.dockerParams.stashContent, is(["buildDescriptor", "pipelineConfigAndTests", "piper-bin", "pipelineStepReports"]))
}
}