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/util/JenkinsShellCallRule.groovy
Marcus Holl e954e3b629 unified behaviour for shell call rule (#794)
* Ensure closure gets called when neither returnStdout nor returnStatus are set

In this case we do not have a return value, but in case we execute a closure we should execute the closure.
With that it is possible to raise an exception from the closure.

* [refactoring] unify usage of unify method call

* Remove dead code.
Coding after uncondition throw exception statement does not get executed.

* Ensure script rule behaves the same whan called with string and with map.
2019-08-02 17:05:49 +02:00

127 lines
3.4 KiB
Groovy

package util
import com.lesfurets.jenkins.unit.BasePipelineTest
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement
class JenkinsShellCallRule implements TestRule {
enum Type { PLAIN, REGEX }
class Command {
final Type type
final String script
Command(Type type, String script) {
this.type = type
this.script = script
}
String toString() {
return "${type} : ${script}"
}
@Override
public int hashCode() {
return type.hashCode() * script.hashCode()
}
@Override
public boolean equals(Object obj) {
if (obj == null || !obj instanceof Command) return false
Command other = (Command) obj
return type == other.type && script == other.script
}
}
final BasePipelineTest testInstance
List shell = []
Map<Command, String> returnValues = [:]
List<Command> failingCommands = []
JenkinsShellCallRule(BasePipelineTest testInstance) {
this.testInstance = testInstance
}
def setReturnValue(script, value) {
setReturnValue(Type.PLAIN, script, value)
}
def setReturnValue(type, script, value) {
returnValues[new Command(type, script)] = value
}
def failExecution(type, script) {
failingCommands.add(new Command(type, script))
}
def handleShellCall(Map parameters) {
def unifiedScript = unify(parameters.script)
shell.add(unifiedScript)
for (Command failingCommand: failingCommands){
if(failingCommand.type == Type.REGEX && unifiedScript =~ failingCommand.script) {
throw new Exception("Script execution failed!")
} else if(failingCommand.type == Type.PLAIN && unifiedScript.equals(failingCommand.script)) {
throw new Exception("Script execution failed!")
}
}
def result = null
for(def e : returnValues.entrySet()) {
if(e.key.type == Type.REGEX && unifiedScript =~ e.key.script) {
result = e.value
break
} else if(e.key.type == Type.PLAIN && unifiedScript.equals(e.key.script)) {
result = e.value
break
}
}
if(result instanceof Closure) result = result()
if (!result && parameters.returnStatus) result = 0
if(! parameters.returnStdout && ! parameters.returnStatus) return
return result
}
@Override
Statement apply(Statement base, Description description) {
return statement(base)
}
private Statement statement(final Statement base) {
return new Statement() {
@Override
void evaluate() throws Throwable {
testInstance.helper.registerAllowedMethod("sh", [String.class], {
command -> handleShellCall([
script: command,
returnStdout: false,
returnStatus: false
])
})
testInstance.helper.registerAllowedMethod("sh", [Map.class], {
m -> handleShellCall(m)
})
base.evaluate()
}
}
}
private static String unify(String s) {
s.replaceAll(/\s+/," ").trim()
}
}