Skip to content

Commit 8c434f5

Browse files
author
Sergei Parshev
committed
MPL-32 Moved to CPS tests by default
1 parent 807fc47 commit 8c434f5

File tree

7 files changed

+201
-56
lines changed

7 files changed

+201
-56
lines changed

test/groovy/com/griddynamics/devops/mpl/modules/Build/BuildTest.groovy

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//
2-
// Copyright (c) 2018 Grid Dynamics International, Inc. All Rights Reserved
2+
// Copyright (c) 2019 Grid Dynamics International, Inc. All Rights Reserved
33
// https://www.griddynamics.com
44
//
55
// Classification level: Public
@@ -73,20 +73,21 @@ class BuildTest extends MPLTestBase {
7373
assertThat(helper.callStack)
7474
.filteredOn { c -> c.methodName == 'tool' }
7575
.filteredOn { c -> c.argsToString().contains('Maven 3') }
76+
.as('Maven 3 tool used')
7677
.isNotEmpty()
7778

7879
assertThat(helper.callStack)
79-
.as('Shell execution should contain mvn command and default clean install')
8080
.filteredOn { c -> c.methodName == 'sh' }
8181
.filteredOn { c -> c.argsToString().startsWith('mvn') }
8282
.filteredOn { c -> c.argsToString().contains('clean install') }
83+
.as('Shell execution should contain mvn command and default clean install')
8384
.isNotEmpty()
8485

8586
assertThat(helper.callStack)
86-
.as('Default mvn run without settings provided')
8787
.filteredOn { c -> c.methodName == 'sh' }
8888
.filteredOn { c -> c.argsToString().startsWith('mvn') }
8989
.filteredOn { c -> ! c.argsToString().contains('-s ') }
90+
.as('Default mvn run without settings provided')
9091
.isNotEmpty()
9192

9293
assertJobStatusSuccess()
@@ -103,9 +104,9 @@ class BuildTest extends MPLTestBase {
103104
printCallStack()
104105

105106
assertThat(helper.callStack)
106-
.as('Changing maven tool name')
107107
.filteredOn { c -> c.methodName == 'tool' }
108108
.filteredOn { c -> c.argsToString().contains('Maven 2') }
109+
.as('Changing maven tool name')
109110
.isNotEmpty()
110111

111112
assertJobStatusSuccess()
@@ -122,9 +123,9 @@ class BuildTest extends MPLTestBase {
122123
printCallStack()
123124

124125
assertThat(helper.callStack)
125-
.as('Providing setings file should set the maven opetion')
126126
.filteredOn { c -> c.methodName == 'sh' }
127127
.filteredOn { c -> c.argsToString().contains("-s '/test-settings.xml'") }
128+
.as('Providing setings file should set the maven opetion')
128129
.isNotEmpty()
129130

130131
assertJobStatusSuccess()

test/groovy/com/griddynamics/devops/mpl/testing/MPLTestBase.groovy

Lines changed: 5 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -23,57 +23,18 @@
2323

2424
package com.griddynamics.devops.mpl.testing
2525

26-
import com.lesfurets.jenkins.unit.BasePipelineTest
26+
import com.griddynamics.devops.mpl.testing.MPLTestBaseSetup
27+
import com.lesfurets.jenkins.unit.cps.BasePipelineTestCPS
2728

28-
import com.griddynamics.devops.mpl.MPLConfig
29-
import com.griddynamics.devops.mpl.MPLManager
30-
import com.griddynamics.devops.mpl.Helper
29+
import com.griddynamics.devops.mpl.testing.MPLTestHelper
3130

32-
import java.security.AccessController
33-
import java.security.PrivilegedAction
34-
import org.codehaus.groovy.runtime.InvokerHelper
35-
36-
abstract class MPLTestBase extends BasePipelineTest {
31+
abstract class MPLTestBase extends BasePipelineTestCPS {
3732
MPLTestBase() {
3833
helper = new MPLTestHelper()
3934
}
4035

4136
void setUp() throws Exception {
4237
super.setUp()
43-
44-
// Overriding Helper to find the right resources in the loaded libs
45-
Helper.metaClass.static.getModulesList = { String path ->
46-
def modules = []
47-
def resourcesFolder = helper.getLibraryClassLoader().getResource('.').getFile()
48-
MPLManager.instance.getModulesLoadPaths().each { modulesPath ->
49-
def libPath = modulesPath + '/' + path
50-
helper.getLibraryClassLoader().getResources(libPath).each { res ->
51-
def libname = res.getFile().substring(resourcesFolder.length())
52-
libname = libname.substring(0, Math.max(libname.indexOf('@'), 0))
53-
modules += [[libname + '/' + libPath, res.text]]
54-
}
55-
}
56-
return modules
57-
}
58-
59-
// Replacing runModule function to mock it
60-
Helper.metaClass.static.runModule = { String source, String path, Map vars = [:] ->
61-
def binding = new Binding()
62-
this.binding.variables.each { k, v -> binding.setVariable(k, v) }
63-
vars.each { k, v -> binding.setVariable(k, v) }
64-
def loader = AccessController.doPrivileged(new PrivilegedAction<GroovyClassLoader>() {
65-
public GroovyClassLoader run() {
66-
return new GroovyClassLoader(helper.getLibraryClassLoader(), helper.getLibraryConfig())
67-
}
68-
})
69-
def script = InvokerHelper.createScript(loader.parseClass(new GroovyCodeSource(source, path, '/mpl/modules'), false), binding)
70-
script.metaClass.invokeMethod = helper.getMethodInterceptor()
71-
script.metaClass.static.invokeMethod = helper.getMethodInterceptor()
72-
script.metaClass.methodMissing = helper.getMethodMissingInterceptor()
73-
script.run()
74-
}
75-
76-
// Show the dump of the configuration during unit tests execution
77-
Helper.metaClass.static.configEntrySet = { Map config -> config.entrySet() }
38+
MPLTestBaseSetup.setUp(helper, this.binding)
7839
}
7940
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//
2+
// Copyright (c) 2018 Grid Dynamics International, Inc. All Rights Reserved
3+
// https://www.griddynamics.com
4+
//
5+
// Classification level: Public
6+
//
7+
// Licensed under the Apache License, Version 2.0 (the "License");
8+
// you may not use this file except in compliance with the License.
9+
// You may obtain a copy of the License at
10+
//
11+
// http://www.apache.org/licenses/LICENSE-2.0
12+
//
13+
// Unless required by applicable law or agreed to in writing, software
14+
// distributed under the License is distributed on an "AS IS" BASIS,
15+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
// See the License for the specific language governing permissions and
17+
// limitations under the License.
18+
//
19+
// $Id: $
20+
// @Project: MPL
21+
// @Description: Shared Jenkins Modular Pipeline Library
22+
//
23+
24+
package com.griddynamics.devops.mpl.testing
25+
26+
import com.griddynamics.devops.mpl.testing.MPLTestBaseSetup
27+
import com.lesfurets.jenkins.unit.BasePipelineTest
28+
29+
import com.griddynamics.devops.mpl.testing.MPLTestHelper
30+
31+
// It's not recommended to use non-cps class for testing - use MPLTestBase instead
32+
abstract class MPLTestBaseNonCPS extends BasePipelineTest {
33+
MPLTestBaseNonCPS() {
34+
helper = new MPLTestHelperNonCPS()
35+
}
36+
37+
void setUp() throws Exception {
38+
super.setUp()
39+
MPLTestBaseSetup.setUp(helper, this.binding)
40+
}
41+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//
2+
// Copyright (c) 2019 Grid Dynamics International, Inc. All Rights Reserved
3+
// https://www.griddynamics.com
4+
//
5+
// Classification level: Public
6+
//
7+
// Licensed under the Apache License, Version 2.0 (the "License");
8+
// you may not use this file except in compliance with the License.
9+
// You may obtain a copy of the License at
10+
//
11+
// http://www.apache.org/licenses/LICENSE-2.0
12+
//
13+
// Unless required by applicable law or agreed to in writing, software
14+
// distributed under the License is distributed on an "AS IS" BASIS,
15+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
// See the License for the specific language governing permissions and
17+
// limitations under the License.
18+
//
19+
// $Id: $
20+
// @Project: MPL
21+
// @Description: Shared Jenkins Modular Pipeline Library
22+
//
23+
24+
package com.griddynamics.devops.mpl.testing
25+
26+
import com.griddynamics.devops.mpl.MPLManager
27+
import com.griddynamics.devops.mpl.Helper
28+
29+
import org.codehaus.groovy.runtime.InvokerHelper
30+
31+
abstract class MPLTestBaseSetup {
32+
static void setUp(helper, context) throws Exception {
33+
// Overriding Helper to find the right resources in the loaded libs
34+
Helper.metaClass.static.getModulesList = { String path ->
35+
def modules = []
36+
def resourcesFolder = helper.getLibraryClassLoader().getResource('.').getFile()
37+
MPLManager.instance.getModulesLoadPaths().each { modulesPath ->
38+
def libPath = modulesPath + '/' + path
39+
helper.getLibraryClassLoader().getResources(libPath).each { res ->
40+
def libname = res.getFile().substring(resourcesFolder.length())
41+
libname = libname.substring(0, Math.max(libname.indexOf('@'), 0))
42+
modules += [[libname + '/' + libPath, res.text]]
43+
}
44+
}
45+
return modules
46+
}
47+
48+
// Replacing runModule function to mock it
49+
Helper.metaClass.static.runModule = { String source, String path, Map vars = [:] ->
50+
def binding = new Binding()
51+
context.variables.each { k, v -> binding.setVariable(k, v) }
52+
vars.each { k, v -> binding.setVariable(k, v) }
53+
def script = InvokerHelper.createScript(helper.getLibraryClassLoader().parseClass(new GroovyCodeSource(source, path, '/mpl/modules'), false), binding)
54+
script.metaClass.invokeMethod = helper.getMethodInterceptor()
55+
script.metaClass.static.invokeMethod = helper.getMethodInterceptor()
56+
script.metaClass.methodMissing = helper.getMethodMissingInterceptor()
57+
script.run()
58+
}
59+
60+
// Show the dump of the configuration during unit tests execution
61+
Helper.metaClass.static.configEntrySet = { Map config -> config.entrySet() }
62+
}
63+
}

test/groovy/com/griddynamics/devops/mpl/testing/MPLTestHelper.groovy

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,15 @@
2323

2424
package com.griddynamics.devops.mpl.testing
2525

26-
import com.lesfurets.jenkins.unit.PipelineTestHelper
26+
import com.lesfurets.jenkins.unit.cps.PipelineTestHelperCPS
2727
import com.lesfurets.jenkins.unit.MethodSignature
2828

29+
import com.cloudbees.groovy.cps.impl.CpsCallableInvocation
30+
import com.cloudbees.groovy.cps.Envs
31+
import com.cloudbees.groovy.cps.Continuation
32+
2933
@groovy.transform.InheritConstructors
30-
class MPLTestHelper extends PipelineTestHelper {
34+
class MPLTestHelper extends PipelineTestHelperCPS {
3135
public getLibraryConfig() {
3236
gse.getConfig()
3337
}
@@ -40,4 +44,33 @@ class MPLTestHelper extends PipelineTestHelper {
4044
return // Skipping methods already existing in the list
4145
allowedMethodCallbacks.put(methodSignature, closure)
4246
}
47+
48+
// To make NotSerializableException more readable
49+
@Override
50+
Object callClosure(Closure closure, Object[] args = null) {
51+
try {
52+
callClosure2(closure, args)
53+
} catch(CpsCallableInvocation e) {
54+
def next = e.invoke(Envs.empty(), null, Continuation.HALT)
55+
while(next.yield==null) {
56+
try {
57+
this.roundtripSerialization(next.e)
58+
} catch (exception) {
59+
throw new Exception("Exception during serialization in `${next.e.closureOwner().class.name}` for class ${exception.getMessage()}", exception)
60+
}
61+
next = next.step()
62+
}
63+
return next.yield.replay()
64+
}
65+
}
66+
67+
Object callClosure2(Closure closure, Object[] args = null) {
68+
if (!args) {
69+
return closure.call()
70+
} else if (args.size() > closure.maximumNumberOfParameters) {
71+
return closure.call(args)
72+
} else {
73+
return closure.call(*args)
74+
}
75+
}
4376
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//
2+
// Copyright (c) 2018 Grid Dynamics International, Inc. All Rights Reserved
3+
// https://www.griddynamics.com
4+
//
5+
// Classification level: Public
6+
//
7+
// Licensed under the Apache License, Version 2.0 (the "License");
8+
// you may not use this file except in compliance with the License.
9+
// You may obtain a copy of the License at
10+
//
11+
// http://www.apache.org/licenses/LICENSE-2.0
12+
//
13+
// Unless required by applicable law or agreed to in writing, software
14+
// distributed under the License is distributed on an "AS IS" BASIS,
15+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
// See the License for the specific language governing permissions and
17+
// limitations under the License.
18+
//
19+
// $Id: $
20+
// @Project: MPL
21+
// @Description: Shared Jenkins Modular Pipeline Library
22+
//
23+
24+
package com.griddynamics.devops.mpl.testing
25+
26+
import com.lesfurets.jenkins.unit.PipelineTestHelper
27+
import com.lesfurets.jenkins.unit.MethodSignature
28+
29+
@groovy.transform.InheritConstructors
30+
class MPLTestHelperNonCPS extends PipelineTestHelper {
31+
public getLibraryConfig() {
32+
gse.getConfig()
33+
}
34+
public getLibraryClassLoader() {
35+
gse.groovyClassLoader
36+
}
37+
38+
void registerAllowedMethod(MethodSignature methodSignature, Closure closure) {
39+
if( isMethodAllowed(methodSignature.name, methodSignature.args) )
40+
return // Skipping methods already existing in the list
41+
allowedMethodCallbacks.put(methodSignature, closure)
42+
}
43+
}

vars/MPLModule.groovy

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ def call(String name = env.STAGE_NAME, cfg = null) {
4747
cfg = cfg.clone()
4848
else
4949
cfg = MPLConfig.create(cfg)
50-
50+
5151
// Trace of the running modules to find loops
5252
// Also to make ability to use lib module from overridden one
5353
def active_modules = MPLManager.instance.getActiveModules()
@@ -64,10 +64,13 @@ def call(String name = env.STAGE_NAME, cfg = null) {
6464
module_src = readFile(project_path)
6565
} else {
6666
// Searching for the not executed module from the loaded libraries
67-
module_src = Helper.getModulesList(module_path).find { it ->
68-
module_path = "library:${it.first()}".toString()
69-
! active_modules.contains(module_path)
70-
}?.last()
67+
def modules = Helper.getModulesList(module_path)
68+
for( def i = 0; i < modules.size(); i++ ) {
69+
if( ! active_modules.contains(module_path) ) {
70+
module_path = "library:${modules[i].first()}".toString()
71+
module_src = modules[i].last()
72+
}
73+
}
7174
}
7275

7376
if( ! module_src )

0 commit comments

Comments
 (0)