From b2dd36fcc7d5135afdb707450a7db8383e64ea68 Mon Sep 17 00:00:00 2001 From: Nestor Acuna-Blanco Date: Fri, 1 Apr 2022 19:42:38 +0200 Subject: [PATCH 1/2] Make bindings accessible in SharedLibrary classes. For the library loading a Pogo is instantiated, which has a different implementation while getting an object. This POGO does not read the bindings. In the PogoMetaClassGetPropertySite the implementation can be found. This throws a runtime exception, which suits well for the common purposes, but not when we try to emulate the Jenkins shared library behaviour. So the workaround is to add the bindings as properties dynamically inside InterceptingGCL. --- .../jenkins/unit/InterceptingGCL.groovy | 3 ++ .../TestSharedLibraryAccessibleParams.groovy | 42 +++++++++++++++++++ .../job/library/params_not_accessible.jenkins | 13 ++++++ .../src/org/test/LibClass.groovy | 7 ++++ 4 files changed, 65 insertions(+) create mode 100644 src/test/groovy/com/lesfurets/jenkins/TestSharedLibraryAccessibleParams.groovy create mode 100644 src/test/jenkins/job/library/params_not_accessible.jenkins create mode 100644 src/test/resources/libs/params_not_accessible/src/org/test/LibClass.groovy diff --git a/src/main/groovy/com/lesfurets/jenkins/unit/InterceptingGCL.groovy b/src/main/groovy/com/lesfurets/jenkins/unit/InterceptingGCL.groovy index 3e04af06..a80d4a50 100644 --- a/src/main/groovy/com/lesfurets/jenkins/unit/InterceptingGCL.groovy +++ b/src/main/groovy/com/lesfurets/jenkins/unit/InterceptingGCL.groovy @@ -12,6 +12,9 @@ class InterceptingGCL extends GroovyClassLoader { metaClazz.static.invokeMethod = helper.getMethodInterceptor() metaClazz.methodMissing = helper.getMethodMissingInterceptor() metaClazz.getEnv = {return binding.env} + binding.variables.forEach { String property, Object value -> + metaClazz."$property" = metaClazz."$property" ?: value + } // find and replace script method closure with any matching allowed method closure metaClazz.methods.forEach { scriptMethod -> def signature = method(scriptMethod.name, scriptMethod.nativeParameterTypes) diff --git a/src/test/groovy/com/lesfurets/jenkins/TestSharedLibraryAccessibleParams.groovy b/src/test/groovy/com/lesfurets/jenkins/TestSharedLibraryAccessibleParams.groovy new file mode 100644 index 00000000..a2891ff1 --- /dev/null +++ b/src/test/groovy/com/lesfurets/jenkins/TestSharedLibraryAccessibleParams.groovy @@ -0,0 +1,42 @@ +package com.lesfurets.jenkins + +import com.lesfurets.jenkins.unit.declarative.DeclarativePipelineTest +import org.junit.Before +import org.junit.Test + +import static com.lesfurets.jenkins.unit.global.lib.LibraryConfiguration.library +import static com.lesfurets.jenkins.unit.global.lib.ProjectSource.projectSource + +class TestSharedLibraryAccessibleParams extends DeclarativePipelineTest { + + private final String JOB_NAME = "params_not_accessible" + private final String JOB_PATH = "job/library/${JOB_NAME}.jenkins" + private final String LIB_DIR = this.class.getResource("/libs/$JOB_NAME").getFile() + + @Override + @Before + void setUp() throws Exception { + scriptRoots += 'src/test/jenkins' + super.setUp() + def library = library().name(JOB_NAME) + .retriever(projectSource(LIB_DIR)) + .defaultVersion("master") + .targetPath(LIB_DIR) + .allowOverride(true) + .implicit(false) + .build() + helper.registerSharedLibrary(library) + } + + @Test + void accessible_params_test() { + binding.setVariable('testVar', 'notBroken') + runScript(JOB_PATH) + assertJobStatusSuccess() + } + + @Test(expected = MissingPropertyException.class) + void not_accessible_params_test() { + runScript(JOB_PATH) + } +} diff --git a/src/test/jenkins/job/library/params_not_accessible.jenkins b/src/test/jenkins/job/library/params_not_accessible.jenkins new file mode 100644 index 00000000..76623edc --- /dev/null +++ b/src/test/jenkins/job/library/params_not_accessible.jenkins @@ -0,0 +1,13 @@ +@Library('params_not_accessible') +import org.test.LibClass + +pipeline { + stages { + stage('Test stage'){ + steps { + out = new LibClass().getX() + echo "Printing ${out}" + } + } + } +} \ No newline at end of file diff --git a/src/test/resources/libs/params_not_accessible/src/org/test/LibClass.groovy b/src/test/resources/libs/params_not_accessible/src/org/test/LibClass.groovy new file mode 100644 index 00000000..3c3b801b --- /dev/null +++ b/src/test/resources/libs/params_not_accessible/src/org/test/LibClass.groovy @@ -0,0 +1,7 @@ +package org.test + +class LibClass { + def getX() { + return testVar + } +} From 2b249fed1b805702cd5e1f17fd942028b1d33b5e Mon Sep 17 00:00:00 2001 From: Nestor Acuna-Blanco Date: Sat, 30 Apr 2022 16:41:38 +0200 Subject: [PATCH 2/2] Adds test case changing the binding value. --- .../TestSharedLibraryAccessibleParams.groovy | 19 ++++++++++++++++--- .../job/library/params_not_accessible.jenkins | 3 ++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/test/groovy/com/lesfurets/jenkins/TestSharedLibraryAccessibleParams.groovy b/src/test/groovy/com/lesfurets/jenkins/TestSharedLibraryAccessibleParams.groovy index a2891ff1..2de29ae8 100644 --- a/src/test/groovy/com/lesfurets/jenkins/TestSharedLibraryAccessibleParams.groovy +++ b/src/test/groovy/com/lesfurets/jenkins/TestSharedLibraryAccessibleParams.groovy @@ -6,12 +6,15 @@ import org.junit.Test import static com.lesfurets.jenkins.unit.global.lib.LibraryConfiguration.library import static com.lesfurets.jenkins.unit.global.lib.ProjectSource.projectSource +import static org.assertj.core.api.Assertions.assertThat class TestSharedLibraryAccessibleParams extends DeclarativePipelineTest { private final String JOB_NAME = "params_not_accessible" private final String JOB_PATH = "job/library/${JOB_NAME}.jenkins" private final String LIB_DIR = this.class.getResource("/libs/$JOB_NAME").getFile() + private final String BINDING_VAR = "testVar" + private final String BINDING_VAL = "notBroken" @Override @Before @@ -30,13 +33,23 @@ class TestSharedLibraryAccessibleParams extends DeclarativePipelineTest { @Test void accessible_params_test() { - binding.setVariable('testVar', 'notBroken') - runScript(JOB_PATH) - assertJobStatusSuccess() + run_test_with_bindings {assertJobStatusSuccess()} + } + + @Test + void change_binding_test() { + run_test_with_bindings {assertThat(binding.getVariable(BINDING_VAR)).isNotEqualTo(BINDING_VAL)} } @Test(expected = MissingPropertyException.class) void not_accessible_params_test() { runScript(JOB_PATH) } + + private void run_test_with_bindings(Closure assertion) { + binding.setVariable(BINDING_VAR, BINDING_VAL) + runScript(JOB_PATH) + assertion() + } + } diff --git a/src/test/jenkins/job/library/params_not_accessible.jenkins b/src/test/jenkins/job/library/params_not_accessible.jenkins index 76623edc..c411260b 100644 --- a/src/test/jenkins/job/library/params_not_accessible.jenkins +++ b/src/test/jenkins/job/library/params_not_accessible.jenkins @@ -6,8 +6,9 @@ pipeline { stage('Test stage'){ steps { out = new LibClass().getX() + testVar = 'changedValue' echo "Printing ${out}" } } } -} \ No newline at end of file +}