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/com/sap/piper/cm/ChangeManagementTest.groovy
2019-03-19 10:07:18 +01:00

512 lines
18 KiB
Groovy

package com.sap.piper.cm
import static org.hamcrest.Matchers.allOf
import static org.hamcrest.Matchers.contains
import static org.hamcrest.Matchers.containsString
import static org.hamcrest.Matchers.equalTo
import static org.hamcrest.Matchers.hasItem
import static org.hamcrest.Matchers.is
import static org.hamcrest.Matchers.not
import static org.junit.Assert.assertThat
import static org.junit.Assert.assertEquals
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 com.sap.piper.GitUtils
import util.BasePiperTest
import util.JenkinsLoggingRule
import util.JenkinsScriptLoaderRule
import util.JenkinsShellCallRule
import util.JenkinsCredentialsRule
import util.JenkinsDockerExecuteRule
import util.Rules
import hudson.AbortException
public class ChangeManagementTest extends BasePiperTest {
private ExpectedException thrown = ExpectedException.none()
private JenkinsShellCallRule script = new JenkinsShellCallRule(this)
private JenkinsLoggingRule logging = new JenkinsLoggingRule(this)
private JenkinsDockerExecuteRule dockerExecuteRule = new JenkinsDockerExecuteRule(this)
@Rule
public RuleChain rules = Rules.getCommonRules(this)
.around(thrown)
.around(script)
.around(logging)
.around(new JenkinsCredentialsRule(this).withCredentials('me','user','password'))
.around(dockerExecuteRule)
@Test
public void testRetrieveChangeDocumentIdOutsideGitWorkTreeTest() {
thrown.expect(ChangeManagementException)
thrown.expectMessage('Cannot retrieve ChangeDocumentId. ' +
'Not in a git work tree. ' +
'ChangeDocumentId is extracted from git commit messages.')
new ChangeManagement(nullScript, gitUtilsMock(false, new String[0])).getChangeDocumentId()
}
@Test
public void testRetrieveChangeDocumentIdNothingFound() {
thrown.expect(ChangeManagementException)
thrown.expectMessage('Cannot retrieve ChangeDocumentId from git commits.')
new ChangeManagement(nullScript, gitUtilsMock(true, new String[0])).getChangeDocumentId()
}
@Test
public void testRetrieveChangeDocumentIdReturnsArrayWithNullValue() {
thrown.expect(ChangeManagementException)
thrown.expectMessage('Cannot retrieve ChangeDocumentId from git commits.')
new ChangeManagement(nullScript, gitUtilsMock(true, (String[])[ null ])).getChangeDocumentId()
}
@Test
public void testRetrieveChangeDocumentNotUnique() {
thrown.expect(ChangeManagementException)
thrown.expectMessage('Multiple ChangeDocumentIds found')
String[] changeIds = [ 'a', 'b' ]
new ChangeManagement(nullScript, gitUtilsMock(true, changeIds)).getChangeDocumentId()
}
@Test
public void testRetrieveChangeDocumentSameChangeIdFoundTwice() {
String[] changeIds = [ 'a', 'a' ]
def changeID = new ChangeManagement(nullScript, gitUtilsMock(true, changeIds)).getChangeDocumentId()
assert changeID == 'a'
}
@Test
public void testIsChangeInDevelopmentReturnsTrueWhenChangeIsInDevelopent() {
script.setReturnValue(JenkinsShellCallRule.Type.REGEX, "cmclient.*is-change-in-development -cID '001'", 0)
boolean inDevelopment = new ChangeManagement(nullScript, null).isChangeInDevelopment(
[
image: 'ppiper/cm-client',
pullImage: true,
],
'001', 'endpoint', 'me')
assertThat(inDevelopment, is(equalTo(true)))
assertThat(script.shell[0], allOf(containsString("cmclient"),
containsString("-u 'user'"),
containsString("-p 'password'"),
containsString("-e 'endpoint'"),
containsString('is-change-in-development'),
containsString("-cID '001'"),
containsString("-t SOLMAN")))
assert dockerExecuteRule.getDockerParams().dockerImage == 'ppiper/cm-client'
assert dockerExecuteRule.getDockerParams().dockerPullImage == true
}
@Test
public void testIsChangeInDevelopmentReturnsFalseWhenChangeIsNotInDevelopent() {
script.setReturnValue(JenkinsShellCallRule.Type.REGEX, "cmclient.*is-change-in-development -cID '001'", 3)
boolean inDevelopment = new ChangeManagement(nullScript, null)
.isChangeInDevelopment([:],
'001',
'endpoint',
'me')
assertThat(inDevelopment, is(equalTo(false)))
}
@Test
public void testIsChangeInDevelopmentThrowsExceptionWhenCMClientReturnsUnexpectedExitCode() {
thrown.expect(ChangeManagementException)
thrown.expectMessage('Cannot retrieve status for change document \'001\'. Does this change exist? Return code from cmclient: 1.')
script.setReturnValue(JenkinsShellCallRule.Type.REGEX, "cmclient.*is-change-in-development -cID '001'", 1)
new ChangeManagement(nullScript, null).isChangeInDevelopment([:], '001', 'endpoint', 'me')
}
@Test
public void testGetCommandLineWithoutCMClientOpts() {
String commandLine = new ChangeManagement(nullScript, null)
.getCMCommandLine(BackendType.SOLMAN,
'https://example.org/cm',
"me",
"topSecret",
"the-command",
["-key1", "val1", "-key2", "val2"])
commandLine = commandLine.replaceAll(' +', " ")
assertThat(commandLine, not(containsString("CMCLIENT_OPTS")))
assertThat(commandLine, containsString("cmclient -e 'https://example.org/cm' -u 'me' -p 'topSecret' -t SOLMAN the-command -key1 val1 -key2 val2"))
}
@Test
public void testGetCommandLineWithCMClientOpts() {
String commandLine = new ChangeManagement(nullScript, null)
.getCMCommandLine(BackendType.SOLMAN,
'https://example.org/cm',
"me",
"topSecret",
"the-command",
["-key1", "val1", "-key2", "val2"],
'-Djavax.net.debug=all')
commandLine = commandLine.replaceAll(' +', " ")
assertThat(commandLine, containsString('export CMCLIENT_OPTS="-Djavax.net.debug=all"'))
}
@Test
public void testCreateTransportRequestSOLMANSucceeds() {
script.setReturnValue(JenkinsShellCallRule.Type.REGEX, ".*cmclient.*create-transport -cID 001 -dID 002.*", '004')
def transportRequestId = new ChangeManagement(nullScript).createTransportRequestSOLMAN(
[
image: 'ppiper/cm-client',
pullImage: true,
],
'001', '002', '003', 'me')
// the check for the transportRequestID is sufficient. This checks implicit the command line since that value is
// returned only in case the shell call matches.
assert transportRequestId == '004'
assert dockerExecuteRule.getDockerParams().dockerImage == 'ppiper/cm-client'
assert dockerExecuteRule.getDockerParams().dockerPullImage == true
}
@Test
public void testCreateTransportRequestRFCSucceeds() {
script.setReturnValue('cts createTransportRequest', '{"REQUESTID":"XYZK9000004"}')
def transportRequestId = new ChangeManagement(nullScript).createTransportRequestRFC(
[image: 'rfc', options: []],
'https://example.org/rfc', // endpoint
'01', // instance
'001', // client
'me', // credentialsId
'Lorem ipsum', // description
true // verbose
)
assert dockerExecuteRule.dockerParams.dockerImage == 'rfc'
assert dockerExecuteRule.dockerParams.dockerEnvVars == [
TRANSPORT_DESCRIPTION: 'Lorem ipsum',
ABAP_DEVELOPMENT_INSTANCE: '01',
ABAP_DEVELOPMENT_CLIENT: '001',
ABAP_DEVELOPMENT_SERVER: 'https://example.org/rfc',
ABAP_DEVELOPMENT_USER: 'user',
ABAP_DEVELOPMENT_PASSWORD: 'password',
VERBOSE: true
]
assert transportRequestId == 'XYZK9000004'
}
@Test
public void testCreateTransportRequestRFCFails() {
thrown.expect(ChangeManagementException)
thrown.expectMessage('Cannot create transport request: script returned exit code 3')
script.setReturnValue('cts createTransportRequest',
{ throw new AbortException('script returned exit code 3')})
def transportRequestId = new ChangeManagement(nullScript).createTransportRequestRFC(
[image: 'rfc', options: []],
'https://example.org/rfc', // endpoint
'001', // client
'01', // instance
'me', // credentialsId
'Lorem ipsum', // description
true, //verbose
)
}
@Test
public void testCreateTransportRequestCTSSucceeds() {
script.setReturnValue(JenkinsShellCallRule.Type.REGEX, 'cmclient.* -t CTS .*create-transport -tt W -ts XYZ -d "desc 123"$', '004')
def transportRequestId = new ChangeManagement(nullScript)
.createTransportRequestCTS(
[
image: 'ppiper/cmclient',
pullImage: true
],
'W', // transport type
'XYZ', // target system
'desc 123', // description
'https://example.org/cm',
'me')
// the check for the transportRequestID is sufficient. This checks implicit the command line since that value is
// returned only in case the shell call matches.
assert transportRequestId == '004'
dockerExecuteRule.getDockerParams().dockerImage = 'ppiper/cmclient'
dockerExecuteRule.getDockerParams().dockerPullImage = true
}
@Test
public void testUploadFileToTransportSucceedsSOLMAN() {
// the regex provided below is an implicit check that the command line is fine.
script.setReturnValue(JenkinsShellCallRule.Type.REGEX, 'upload-file-to-transport.*-cID 001 -tID 002 XXX "/path"', 0)
new ChangeManagement(nullScript).uploadFileToTransportRequestSOLMAN(
[
image: 'ppiper/cm-client',
imagePull: true,
],
'001',
'002',
'XXX',
'/path',
'https://example.org/cm',
'me')
// no assert required here for the shell script, since the regex registered above
// to the script rule is an implicit check for the command line.
dockerExecuteRule.getDockerParams().dockerImage = 'ppiper/cmclient'
dockerExecuteRule.getDockerParams().dockerPullImage = true
}
@Test
public void testUploadFileToTransportSucceedsCTS() {
// the regex provided below is an implicit check that the command line is fine.
script.setReturnValue(JenkinsShellCallRule.Type.REGEX, '-t CTS upload-file-to-transport -tID 002 "/path"', 0)
new ChangeManagement(nullScript).uploadFileToTransportRequestCTS(
[
image: 'ppiper/cmclient',
pullImage: true
],
'002',
'/path',
'https://example.org/cm',
'me')
assert dockerExecuteRule.getDockerParams().dockerImage == 'ppiper/cmclient'
assert dockerExecuteRule.getDockerParams().dockerPullImage == true
// no assert for the shell command required here, since the regex registered
// above to the script rule is an implicit check for the command line.
}
@Test
public void testUploadFileToTransportSucceedsRFC() {
new ChangeManagement(nullScript).uploadFileToTransportRequestRFC(
[image:'rfc', options: [], pullImage: true],
'002', //transportRequestId
'001', // applicationId
'https://example.org/mypath/deployArtifact.zip',
'https://example.org/rfc',
'me',
'00', //developmentInstance
'001', // developmentClient
'Lorem ipsum', // applicationDescription
'XYZ', // abapPackage
'UTF-9', //codePage
true, // accept unix style EOL
true, // failUploadOnWarning
false, // verbose
)
assert dockerExecuteRule.dockerParams.dockerImage == 'rfc'
assert dockerExecuteRule.dockerParams.dockerPullImage == true
assert dockerExecuteRule.dockerParams.dockerEnvVars ==
[
ABAP_DEVELOPMENT_INSTANCE: '00',
ABAP_DEVELOPMENT_CLIENT: '001',
ABAP_APPLICATION_NAME: '001',
ABAP_APPLICATION_DESC: 'Lorem ipsum',
ABAP_PACKAGE: 'XYZ',
ZIP_FILE_URL: 'https://example.org/mypath/deployArtifact.zip',
ABAP_DEVELOPMENT_SERVER: 'https://example.org/rfc',
ABAP_DEVELOPMENT_USER: 'user',
ABAP_DEVELOPMENT_PASSWORD: 'password',
CODE_PAGE: 'UTF-9',
ABAP_ACCEPT_UNIX_STYLE_EOL: 'X',
FAIL_UPLOAD_ON_WARNING: 'true',
VERBOSE: 'false'
]
assertThat(script.shell, contains('cts uploadToABAP:002'))
}
@Test
public void testUploadFileToTransportFailsRFC() {
thrown.expect(ChangeManagementException)
thrown.expectMessage('Cannot upload file into transport request. Return code from rfc client: 1.')
script.setReturnValue('cts uploadToABAP:002', 1)
new ChangeManagement(nullScript).uploadFileToTransportRequestRFC(
[:],
'002', //transportRequestId
'001', // applicationId
'https://example.org/mypath/deployArtifact.zip',
'https://example.org/rfc',
'me',
'00', //developmentInstance
'001', // developmentClient
'Lorem ipsum', // applicationDescription
'XYZ', // abapPackage
'UTF-9', // codePage
true, // accept unix style EOL
true, // failUploadOnWarning
false, // verbose
)
}
@Test
public void testUploadFileToTransportFailsSOLMAN() {
thrown.expect(ChangeManagementException)
thrown.expectMessage("Cannot upload file into transport request. " +
"Return code from cm client: 1.")
script.setReturnValue(JenkinsShellCallRule.Type.REGEX,, 'upload-file-to-transport', 1)
new ChangeManagement(nullScript).uploadFileToTransportRequestSOLMAN(
[:],
'001',
'002',
'XXX',
'/path',
'https://example.org/cm',
'me')
}
@Test
public void testReleaseTransportRequestSucceedsSOLMAN() {
// the regex provided below is an implicit check that the command line is fine.
script.setReturnValue(JenkinsShellCallRule.Type.REGEX, '-t SOLMAN release-transport.*-cID 001.*-tID 002', 0)
new ChangeManagement(nullScript).releaseTransportRequestSOLMAN(
[
image: 'ppiper/cm-client',
imagePull: true,
],
'001',
'002',
'https://example.org',
'me',
'openSesame')
// no assert required here, since the regex registered above to the script rule is an implicit check for
// the command line.
dockerExecuteRule.getDockerParams().dockerImage == 'ppiper/cm-client'
dockerExecuteRule.getDockerParams().pullImage == true
}
@Test
public void testReleaseTransportRequestSucceedsCTS() {
// the regex provided below is an implicit check that the command line is fine.
script.setReturnValue(JenkinsShellCallRule.Type.REGEX, '-t CTS export-transport.*-tID 002', 0)
new ChangeManagement(nullScript).releaseTransportRequestCTS(
[
image: 'ppiper/cm-client',
pullImage: true,
],
'002',
'https://example.org',
'me',
'openSesame')
// no assert required here, since the regex registered above to the script rule is an implicit check for
// the command line.
assert dockerExecuteRule.getDockerParams().dockerImage == 'ppiper/cm-client'
assert dockerExecuteRule.getDockerParams().dockerPullImage == true
}
@Test
public void testReleaseTransportRequestSucceedsRFC() {
new ChangeManagement(nullScript).releaseTransportRequestRFC(
[:],
'002',
'https://example.org',
'002',
'001',
'me',
true)
assert dockerExecuteRule.dockerParams.dockerEnvVars == [
ABAP_DEVELOPMENT_SERVER: 'https://example.org',
ABAP_DEVELOPMENT_USER: 'user',
ABAP_DEVELOPMENT_PASSWORD: 'password',
ABAP_DEVELOPMENT_CLIENT: '001',
ABAP_DEVELOPMENT_INSTANCE: '002',
VERBOSE: true,
]
assertThat(script.shell, hasItem('cts releaseTransport:002'))
}
@Test
public void testReleaseTransportRequestFailsSOLMAN() {
thrown.expect(ChangeManagementException)
thrown.expectMessage("Cannot release Transport Request '002'. Return code from cmclient: 1.")
// the regex provided below is an implicit check that the command line is fine.
script.setReturnValue(JenkinsShellCallRule.Type.REGEX, 'release-transport.*-cID 001.*-tID 002', 1)
new ChangeManagement(nullScript).releaseTransportRequestSOLMAN(
[
image: 'ppiper/cm-client',
imagePull: true,
],
'001',
'002',
'https://example.org',
'me')
}
private GitUtils gitUtilsMock(boolean insideWorkTree, String[] changeIds) {
return new GitUtils() {
public boolean insideWorkTree() {
return insideWorkTree
}
public String[] extractLogLines(
String filter = '',
String from = 'origin/master',
String to = 'HEAD',
String format = '%b') {
return changeIds
}
}
}
}