-
Notifications
You must be signed in to change notification settings - Fork 334
Expand file tree
/
Copy pathInstrumentPluginTest.groovy
More file actions
121 lines (100 loc) · 3.18 KB
/
InstrumentPluginTest.groovy
File metadata and controls
121 lines (100 loc) · 3.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import net.bytebuddy.utility.OpenedClassReader
import org.gradle.testkit.runner.BuildResult
import org.gradle.testkit.runner.GradleRunner
import org.objectweb.asm.ClassReader
import org.objectweb.asm.ClassVisitor
import org.objectweb.asm.FieldVisitor
import spock.lang.Specification
import spock.lang.TempDir
class InstrumentPluginTest extends Specification {
def buildGradle = '''
plugins {
id 'java'
id 'instrument'
}
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
repositories {
mavenCentral()
}
dependencies {
compileOnly group: 'net.bytebuddy', name: 'byte-buddy', version: '1.15.11' // just to build TestPlugin
}
apply plugin: 'instrument'
instrument.plugins = [
'TestPlugin'
]
'''
def testPlugin = '''
import java.io.File;
import java.io.IOException;
import net.bytebuddy.build.Plugin;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.ClassFileLocator;
import net.bytebuddy.dynamic.DynamicType;
public class TestPlugin implements Plugin {
private final File targetDir;
public TestPlugin(File targetDir) {
this.targetDir = targetDir;
}
@Override
public boolean matches(TypeDescription target) {
return "ExampleCode".equals(target.getSimpleName());
}
@Override
public DynamicType.Builder<?> apply(
DynamicType.Builder<?> builder,
TypeDescription typeDescription,
ClassFileLocator classFileLocator) {
return builder.defineField("__TEST__FIELD__", Void.class);
}
@Override
public void close() throws IOException {
// no-op
}
}
'''
def exampleCode = '''
package example; public class ExampleCode {}
'''
@TempDir
File buildDir
def 'test instrument plugin'() {
setup:
def tree = new FileTreeBuilder(buildDir)
tree.'build.gradle'(buildGradle)
tree.src {
main {
java {
'TestPlugin.java'(testPlugin)
example {
'ExampleCode.java'(exampleCode)
}
}
}
}
when:
BuildResult result = GradleRunner.create()
.withTestKitDir(new File(buildDir, '.gradle-test-kit')) // workaround in case the global test-kit cache becomes corrupted
.withDebug(true) // avoids starting daemon which can leave undeleted files post-cleanup
.withProjectDir(buildDir)
.withArguments('build', '--stacktrace')
.withPluginClasspath()
.forwardOutput()
.build()
File classFile = new File(buildDir, 'build/classes/java/main/example/ExampleCode.class')
then:
assert classFile.isFile()
boolean foundInsertedField = false
new ClassReader(new FileInputStream(classFile)).accept(new ClassVisitor(OpenedClassReader.ASM_API) {
@Override
FieldVisitor visitField(int access, String fieldName, String descriptor, String signature, Object value) {
if ('__TEST__FIELD__' == fieldName) {
foundInsertedField = true
}
return null
}
}, OpenedClassReader.ASM_API)
assert foundInsertedField
}
}