Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't use a single type in MockScriptHandler constructor #541

Merged
merged 2 commits into from
Jul 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 113 additions & 30 deletions src/main/groovy/com/lesfurets/jenkins/unit/PipelineTestHelper.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -28,30 +28,47 @@ class PipelineTestHelper {
*/
class MockScriptHandler {
/**
* filter used to determine whether a script matches this mock
*
* The given pattern can be
* - null, which matches anything
* - a string, which means a full match
* - a pattern, which means a pattern match
* Filters used to determine whether a script matches this mock. If both values are null, then no filter is used
* and all scripts are matched.
*/
Object filter = null
String fullMatchFilter = null
Pattern regexpMatchFilter = null

// mocked script results, specified as either value or callback
String stdout = null
int exitValue = -1
Closure callback = null

MockScriptHandler(Object filter, String stdout, int exitValue) {
assert (filter == null || filter instanceof String || filter instanceof Pattern)
this.filter = filter
MockScriptHandler(String stdout, int exitValue) {
this.fullMatchFilter = null
this.regexpMatchFilter = null
this.stdout = stdout
this.exitValue = exitValue
}

MockScriptHandler(String filter, String stdout, int exitValue) {
this.fullMatchFilter = filter
this.regexpMatchFilter = null
this.stdout = stdout
this.exitValue = exitValue
}

MockScriptHandler(Pattern filter, String stdout, int exitValue) {
this.fullMatchFilter = null
this.regexpMatchFilter = filter
this.stdout = stdout
this.exitValue = exitValue
}

MockScriptHandler(Object filter, Closure callback) {
assert (filter == null || filter instanceof String || filter instanceof Pattern)
this.filter = filter
MockScriptHandler(String filter, Closure callback) {
this.fullMatchFilter = filter
this.regexpMatchFilter = null
this.callback = callback
}

MockScriptHandler(Pattern filter, Closure callback) {
this.fullMatchFilter = null
this.regexpMatchFilter = filter
this.callback = callback
}

Expand All @@ -60,20 +77,20 @@ class PipelineTestHelper {
*/
private List match(String script) {
// if no filter is set, this matches everything
if (filter == null) {
if (fullMatchFilter == null && regexpMatchFilter == null) {
return [script]
}

// if a string is specified, perform a simple string comparison
if (filter instanceof String) {
return (filter == script) ? [script] : null
if (fullMatchFilter) {
return (fullMatchFilter == script) ? [script] : null
}

// if an actual pattern is specified, perform a pattern match
// Note that this does a full match, i.e. the call string must
// match completely!
if (filter instanceof Pattern) {
def matcher = script =~ filter
if (regexpMatchFilter) {
def matcher = script =~ regexpMatchFilter
if (!matcher.matches()) {
return null
}
Expand Down Expand Up @@ -141,10 +158,10 @@ class PipelineTestHelper {
}

/** Holds configured mock script handlers for the `sh` command. */
List<MockScriptHandler> mockShHandlers = [new MockScriptHandler(null, '', 0)]
List<MockScriptHandler> mockShHandlers = [new MockScriptHandler('', 0)]

/** Holds configured mock script handlers for the `bat` command. */
List<MockScriptHandler> mockBatHandlers = [new MockScriptHandler(null, '', 0)]
List<MockScriptHandler> mockBatHandlers = [new MockScriptHandler('', 0)]

/**
* Search paths for scripts
Expand Down Expand Up @@ -403,8 +420,8 @@ class PipelineTestHelper {
gse = new GroovyScriptEngine(scriptRoots, cLoader)
gse.setConfig(configuration)

mockShHandlers = [new MockScriptHandler(null, '', 0)]
mockBatHandlers = [new MockScriptHandler(null, '', 0)]
mockShHandlers = [new MockScriptHandler('', 0)]
mockBatHandlers = [new MockScriptHandler('', 0)]
mockFileExistsResults.clear()
mockReadFileOutputs.clear()
return this
Expand Down Expand Up @@ -766,18 +783,56 @@ class PipelineTestHelper {
/**
* Configure mock output for the `sh` command. This function should be called before
* attempting to call `JenkinsMocks.sh()`.
* @param filter Script command or pattern to mock or null if any command is matched.
* @param stdout Standard output text to return for the given command.
* @param exitValue Exit value for the command.
*/
void addShMock(Object filter, String stdout, int exitValue) {
void addShMock(String stdout, int exitValue) {
mockShHandlers << new MockScriptHandler(stdout, exitValue)
}

/**
* Configure mock output for the `sh` command. This function should be called before
* attempting to call `JenkinsMocks.sh()`.
* @param filter Script command to mock or null if any command is matched.
* @param stdout Standard output text to return for the given command.
* @param exitValue Exit value for the command.
*/
void addShMock(String filter, String stdout, int exitValue) {
mockShHandlers << new MockScriptHandler(filter, stdout, exitValue)
}

/**
* Configure mock output for the `sh` command. This function should be called before
* attempting to call `JenkinsMocks.sh()`.
* @param filter Regexp pattern to mock or null if any command is matched.
* @param stdout Standard output text to return for the given command.
* @param exitValue Exit value for the command.
*/
void addShMock(Pattern filter, String stdout, int exitValue) {
mockShHandlers << new MockScriptHandler(filter, stdout, exitValue)
}

/**
* Configure mock callback for the `sh` command. This function should be called before
* attempting to call `JenkinsMocks.sh()`.
* @param filter Script command to mock or null if any command is matched.
* @param callback Closure to be called when the mock is executed. This closure will be
* passed the script call which is being executed, and
* <strong>must</strong> return a {@code Map} with the following
* key/value pairs:
* <ul>
* <li>{@code stdout}: {@code String} with the mocked output.</li>
* <li>{@code exitValue}: {@code int} with the mocked exit value.</li>
* </ul>
*/
void addShMock(String filter, Closure callback) {
mockShHandlers << new MockScriptHandler(filter, callback)
}

/**
* Configure mock callback for the `sh` command. This function should be called before
* attempting to call `JenkinsMocks.sh()`.
* @param filter Script command or pattern to mock or null if any command is matched.
* @param filter Regexp pattern to mock or null if any command is matched.
* @param callback Closure to be called when the mock is executed. This closure will be
* passed the script call which is being executed, and
* <strong>must</strong> return a {@code Map} with the following
Expand All @@ -787,7 +842,7 @@ class PipelineTestHelper {
* <li>{@code exitValue}: {@code int} with the mocked exit value.</li>
* </ul>
*/
void addShMock(Object filter, Closure callback) {
void addShMock(Pattern filter, Closure callback) {
mockShHandlers << new MockScriptHandler(filter, callback)
}

Expand All @@ -799,18 +854,46 @@ class PipelineTestHelper {
/**
* Configure mock output for the `bat` command. This function should be called before
* attempting to call `JenkinsMocks.bat()`.
* @param filter Script command or pattern to mock or null if any command is matched.
* @param filter Script command to mock or null if any command is matched.
* @param stdout Standard output text to return for the given command.
* @param exitValue Exit value for the command.
*/
void addBatMock(String filter, String stdout, int exitValue) {
mockBatHandlers << new MockScriptHandler(filter, stdout, exitValue)
}

/**
* Configure mock output for the `bat` command. This function should be called before
* attempting to call `JenkinsMocks.bat()`.
* @param filter Regexp pattern to mock or null if any command is matched.
* @param stdout Standard output text to return for the given command.
* @param exitValue Exit value for the command.
*/
void addBatMock(Object filter, String stdout, int exitValue) {
void addBatMock(Pattern filter, String stdout, int exitValue) {
mockBatHandlers << new MockScriptHandler(filter, stdout, exitValue)
}

/**
* Configure mock callback for the `bat` command. This function should be called before
* attempting to call `JenkinsMocks.bat()`.
* @param filter Script command or pattern to mock or null if any command is matched.
* @param filter Script command to mock or null if any command is matched.
* @param callback Closure to be called when the mock is executed. This closure will be
* passed the script call which is being executed, and
* <strong>must</strong> return a {@code Map} with the following
* key/value pairs:
* <ul>
* <li>{@code stdout}: {@code String} with the mocked output.</li>
* <li>{@code exitValue}: {@code int} with the mocked exit value.</li>
* </ul>
*/
void addBatMock(String filter, Closure callback) {
mockBatHandlers << new MockScriptHandler(filter, callback)
}

/**
* Configure mock callback for the `bat` command. This function should be called before
* attempting to call `JenkinsMocks.bat()`.
* @param filter Regexp pattern to mock or null if any command is matched.
* @param callback Closure to be called when the mock is executed. This closure will be
* passed the script call which is being executed, and
* <strong>must</strong> return a {@code Map} with the following
Expand All @@ -820,7 +903,7 @@ class PipelineTestHelper {
* <li>{@code exitValue}: {@code int} with the mocked exit value.</li>
* </ul>
*/
void addBatMock(Object filter, Closure callback) {
void addBatMock(Pattern filter, Closure callback) {
mockBatHandlers << new MockScriptHandler(filter, callback)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,32 @@ class PipelineTestHelperTest {
assertThat(status).isEqualTo(2)
}

@Test()
void runShWithPatternStatus() {
// given:
def helper = new PipelineTestHelper()
helper.addShMock(~/echo\s(.*)/, 'mock-output', 777)

// when:
def status = helper.runSh(returnStatus: true, script: 'echo foo')

// then:
assertThat(status).isEqualTo(777)
}

@Test()
void runShWithPatternStdout() {
// given:
def helper = new PipelineTestHelper()
helper.addShMock(~/echo\s(.*)/, 'mock-output', 0)

// when:
def status = helper.runSh(returnStdout: true, script: 'echo foo')

// then:
assertThat(status).isEqualTo('mock-output')
}

@Test()
void runShWithDefaultPattern() {
// given:
Expand Down Expand Up @@ -341,7 +367,7 @@ class PipelineTestHelperTest {
void runShWithDefaultHandler() {
// given:
helper.addShMock('command', 'ignored', 0)
helper.addShMock(null, 'default', 1)
helper.addShMock('default', 1)
helper.addShMock('pwd', 'ignored', 2)

// when:
Expand Down