1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2024-12-12 10:55:20 +02:00
sap-jenkins-library/consumer-test/TestRunnerThread.groovy
2020-04-11 12:27:27 +02:00

146 lines
5.4 KiB
Groovy

@Grab('org.yaml:snakeyaml:1.17')
import org.yaml.snakeyaml.Yaml
class TestRunnerThread extends Thread {
static def workspacesRootDir
static def libraryVersionUnderTest
static def repositoryUnderTest
Process currentProcess
final StringBuilder stdOut = new StringBuilder()
final StringBuilder stdErr = new StringBuilder()
int lastPrintedStdOutLine = -1
public def returnCode = -1
public def lastCommand
def area
def testCase
def uniqueName
def testCaseRootDir
def testCaseWorkspace
def testCaseConfig
TestRunnerThread(File testCaseFile) {
this.testCaseConfig = new Yaml().load(testCaseFile.text)
if (!System.getenv(testCaseConfig.deployCredentialEnv.username) ||
!System.getenv(testCaseConfig.deployCredentialEnv.password)) {
throw new RuntimeException("Environment variables '${testCaseConfig.deployCredentialEnv.username}' and '${testCaseConfig.deployCredentialEnv.password}' need to be set.")
}
// Regex pattern expects a folder structure such as '/rootDir/areaDir/testCase.extension'
def testCaseMatches = (testCaseFile.toString() =~
/^[\w\-]+\\/([\w\-]+)\\/([\w\-]+)\..*\u0024/)
this.area = testCaseMatches[0][1]
this.testCase = testCaseMatches[0][2]
if (!area || !testCase) {
throw new RuntimeException("Expecting file structure '/rootDir/areaDir/testCase.yml' " +
"but got '${testCaseFile}'.")
}
this.uniqueName = "${area}|${testCase}"
this.testCaseRootDir = new File("${workspacesRootDir}/${area}/${testCase}")
this.testCaseWorkspace = "${testCaseRootDir}/workspace"
}
void run() {
println "[INFO] Test case '${uniqueName}' launched."
if (testCaseRootDir.exists() || !testCaseRootDir.mkdirs()) {
throw new RuntimeException("Creation of dir '${testCaseRootDir}' failed.")
}
executeShell("git clone -b ${testCaseConfig.referenceAppRepo.branch} " +
"${testCaseConfig.referenceAppRepo.url} ${testCaseWorkspace}")
addJenkinsYmlToWorkspace()
setLibraryVersionInJenkinsfile()
//Commit the changed version because artifactSetVersion expects the git repo not to be dirty
executeShell(["git", "-C", "${testCaseWorkspace}", "commit", "--all",
'--author="piper-testing-bot <piper-testing-bot@example.com>"',
'--message="Set piper lib version for test"'])
executeShell("docker run --rm -v /var/run/docker.sock:/var/run/docker.sock " +
"-v ${System.getenv('PWD')}/${testCaseWorkspace}:/workspace -v /tmp " +
"-e CASC_JENKINS_CONFIG=/workspace/jenkins.yml " +
"-e ${testCaseConfig.deployCredentialEnv.username} " +
"-e ${testCaseConfig.deployCredentialEnv.password} " +
"-e LIBRARY_VERSION_UNDER_TEST=${libraryVersionUnderTest} " +
"-e REPOSITORY_UNDER_TEST=${repositoryUnderTest} " +
"-e BRANCH_NAME=${testCaseConfig.referenceAppRepo.branch} ppiper/jenkinsfile-runner")
println "*****[INFO] Test case '${uniqueName}' finished successfully.*****"
printOutput()
}
// Configure path to library-repository under test in Jenkins config
private void addJenkinsYmlToWorkspace() {
def sourceFile = 'jenkins.yml'
def sourceText = new File(sourceFile).text.replaceAll(
'__REPO_SLUG__', repositoryUnderTest)
def target = new File("${testCaseWorkspace}/${sourceFile}")
target.write(sourceText)
}
// Force usage of library version under test by setting it in the Jenkinsfile,
// which is then the first definition and thus has the highest precedence.
private void setLibraryVersionInJenkinsfile() {
def jenkinsfile = new File("${testCaseWorkspace}/Jenkinsfile")
def manipulatedText =
"@Library(\"piper-lib-os@${libraryVersionUnderTest}\") _\n" +
jenkinsfile.text
jenkinsfile.write(manipulatedText)
}
private void executeShell(command) {
lastCommand = command
def startOfCommandString = "Shell command: '${command}'\n"
stdOut << startOfCommandString
stdErr << startOfCommandString
currentProcess = command.execute()
currentProcess.waitForProcessOutput(stdOut, stdErr)
returnCode = currentProcess.exitValue()
currentProcess = null
if (returnCode > 0) {
throw new ReturnCodeNotZeroException("Test case: [${uniqueName}]; " +
"shell command '${command} exited with return code '${returnCode}")
}
}
void printOutput() {
println "\n[INFO] stdout output from test case ${uniqueName}:"
stdOut.eachLine { line, i ->
println "${i} [${uniqueName}] ${line}"
lastPrintedStdOutLine = i
}
println "\n[INFO] stderr output from test case ${uniqueName}:"
stdErr.eachLine { line, i ->
println "${i} [${uniqueName}] ${line}"
}
}
public void printRunningStdOut() {
stdOut.eachLine { line, i ->
if (i > lastPrintedStdOutLine) {
println "${i} [${uniqueName}] ${line}"
lastPrintedStdOutLine = i
}
}
}
@Override
public String toString() {
return uniqueName
}
}
class ReturnCodeNotZeroException extends Exception {
ReturnCodeNotZeroException(message) {
super(message)
}
}