252 lines
8.6 KiB
Groovy
252 lines
8.6 KiB
Groovy
/*
|
|
* Copyright The OpenTelemetry Authors
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
package muzzle
|
|
|
|
import static io.opentelemetry.javaagent.tooling.muzzle.Reference.Flag.ManifestationFlag
|
|
import static io.opentelemetry.javaagent.tooling.muzzle.Reference.Flag.MinimumVisibilityFlag
|
|
import static io.opentelemetry.javaagent.tooling.muzzle.Reference.Flag.OwnershipFlag
|
|
import static io.opentelemetry.javaagent.tooling.muzzle.Reference.Flag.VisibilityFlag
|
|
import static muzzle.TestClasses.HelperAdvice
|
|
import static muzzle.TestClasses.LdcAdvice
|
|
import static muzzle.TestClasses.MethodBodyAdvice
|
|
|
|
import io.opentelemetry.instrumentation.OtherTestHelperClasses
|
|
import io.opentelemetry.instrumentation.TestHelperClasses
|
|
import io.opentelemetry.instrumentation.test.AgentTestRunner
|
|
import io.opentelemetry.javaagent.tooling.muzzle.Reference
|
|
import io.opentelemetry.javaagent.tooling.muzzle.collector.ReferenceCollector
|
|
|
|
class ReferenceCollectorTest extends AgentTestRunner {
|
|
def "method body creates references"() {
|
|
setup:
|
|
def collector = new ReferenceCollector()
|
|
collector.collectReferencesFrom(MethodBodyAdvice.name)
|
|
def references = collector.getReferences()
|
|
|
|
expect:
|
|
references.keySet() == [
|
|
MethodBodyAdvice.A.name,
|
|
MethodBodyAdvice.B.name,
|
|
MethodBodyAdvice.SomeInterface.name,
|
|
MethodBodyAdvice.SomeImplementation.name
|
|
] as Set
|
|
|
|
def bRef = references[MethodBodyAdvice.B.name]
|
|
def aRef = references[MethodBodyAdvice.A.name]
|
|
|
|
// interface flags
|
|
bRef.flags.contains(ManifestationFlag.NON_INTERFACE)
|
|
references[MethodBodyAdvice.SomeInterface.name].flags.contains(ManifestationFlag.INTERFACE)
|
|
|
|
// class access flags
|
|
aRef.flags.contains(MinimumVisibilityFlag.PACKAGE_OR_HIGHER)
|
|
bRef.flags.contains(MinimumVisibilityFlag.PACKAGE_OR_HIGHER)
|
|
|
|
// method refs
|
|
assertMethod bRef, 'method', '(Ljava/lang/String;)Ljava/lang/String;',
|
|
MinimumVisibilityFlag.PROTECTED_OR_HIGHER,
|
|
OwnershipFlag.NON_STATIC
|
|
assertMethod bRef, 'methodWithPrimitives', '(Z)V',
|
|
MinimumVisibilityFlag.PROTECTED_OR_HIGHER,
|
|
OwnershipFlag.NON_STATIC
|
|
assertMethod bRef, 'staticMethod', '()V',
|
|
MinimumVisibilityFlag.PROTECTED_OR_HIGHER,
|
|
OwnershipFlag.STATIC
|
|
assertMethod bRef, 'methodWithArrays', '([Ljava/lang/String;)[Ljava/lang/Object;',
|
|
MinimumVisibilityFlag.PROTECTED_OR_HIGHER,
|
|
OwnershipFlag.NON_STATIC
|
|
|
|
// field refs
|
|
bRef.fields.isEmpty()
|
|
aRef.fields.size() == 2
|
|
assertField aRef, 'publicB', MinimumVisibilityFlag.PACKAGE_OR_HIGHER, OwnershipFlag.NON_STATIC
|
|
assertField aRef, 'staticB', MinimumVisibilityFlag.PACKAGE_OR_HIGHER, OwnershipFlag.STATIC
|
|
}
|
|
|
|
def "protected ref test"() {
|
|
setup:
|
|
def collector = new ReferenceCollector()
|
|
collector.collectReferencesFrom(MethodBodyAdvice.B2.name)
|
|
def references = collector.getReferences()
|
|
|
|
expect:
|
|
assertMethod references[MethodBodyAdvice.B.name], 'protectedMethod', '()V',
|
|
MinimumVisibilityFlag.PROTECTED_OR_HIGHER,
|
|
OwnershipFlag.NON_STATIC
|
|
}
|
|
|
|
def "ldc creates references"() {
|
|
setup:
|
|
def collector = new ReferenceCollector()
|
|
collector.collectReferencesFrom(LdcAdvice.name)
|
|
def references = collector.getReferences()
|
|
|
|
expect:
|
|
references[MethodBodyAdvice.A.name] != null
|
|
}
|
|
|
|
def "instanceof creates references"() {
|
|
setup:
|
|
def collector = new ReferenceCollector()
|
|
collector.collectReferencesFrom(TestClasses.InstanceofAdvice.name)
|
|
def references = collector.getReferences()
|
|
|
|
expect:
|
|
references[MethodBodyAdvice.A.name] != null
|
|
}
|
|
|
|
def "invokedynamic creates references"() {
|
|
setup:
|
|
def collector = new ReferenceCollector()
|
|
collector.collectReferencesFrom(TestClasses.InvokeDynamicAdvice.name)
|
|
def references = collector.getReferences()
|
|
|
|
expect:
|
|
references['muzzle.TestClasses$MethodBodyAdvice$SomeImplementation'] != null
|
|
references['muzzle.TestClasses$MethodBodyAdvice$B'] != null
|
|
}
|
|
|
|
def "should create references for helper classes"() {
|
|
when:
|
|
def collector = new ReferenceCollector()
|
|
collector.collectReferencesFrom(HelperAdvice.name)
|
|
def references = collector.getReferences()
|
|
|
|
then:
|
|
references.keySet() == [
|
|
TestHelperClasses.Helper.name,
|
|
TestHelperClasses.HelperSuperClass.name,
|
|
TestHelperClasses.HelperInterface.name
|
|
] as Set
|
|
|
|
with(references[TestHelperClasses.HelperSuperClass.name]) { helperSuperClass ->
|
|
helperSuperClass.flags.contains(ManifestationFlag.ABSTRACT)
|
|
assertHelperSuperClassMethod(helperSuperClass, true)
|
|
assertMethod helperSuperClass, 'finalMethod', '()Ljava/lang/String;',
|
|
VisibilityFlag.PUBLIC,
|
|
OwnershipFlag.NON_STATIC,
|
|
ManifestationFlag.FINAL
|
|
}
|
|
|
|
with(references[TestHelperClasses.HelperInterface.name]) { helperInterface ->
|
|
helperInterface.flags.contains(ManifestationFlag.ABSTRACT)
|
|
assertHelperInterfaceMethod helperInterface, true
|
|
}
|
|
|
|
with(references[TestHelperClasses.Helper.name]) { helperClass ->
|
|
helperClass.flags.contains(ManifestationFlag.NON_FINAL)
|
|
assertHelperSuperClassMethod helperClass, false
|
|
assertHelperInterfaceMethod helperClass, false
|
|
}
|
|
}
|
|
|
|
def "should find all helper classes"() {
|
|
when:
|
|
def collector = new ReferenceCollector()
|
|
collector.collectReferencesFrom(HelperAdvice.name)
|
|
def helperClasses = collector.getSortedHelperClasses()
|
|
|
|
then:
|
|
assertThatContainsInOrder helperClasses, [
|
|
TestHelperClasses.HelperInterface.name,
|
|
TestHelperClasses.Helper.name
|
|
]
|
|
assertThatContainsInOrder helperClasses, [
|
|
TestHelperClasses.HelperSuperClass.name,
|
|
TestHelperClasses.Helper.name
|
|
]
|
|
}
|
|
|
|
def "should correctly find helper classes from multiple advice classes"() {
|
|
when:
|
|
def collector = new ReferenceCollector()
|
|
collector.collectReferencesFrom(TestClasses.HelperAdvice.name)
|
|
collector.collectReferencesFrom(TestClasses.HelperOtherAdvice.name)
|
|
def helperClasses = collector.getSortedHelperClasses()
|
|
|
|
then:
|
|
assertThatContainsInOrder helperClasses, [
|
|
TestHelperClasses.HelperInterface.name,
|
|
TestHelperClasses.Helper.name
|
|
]
|
|
assertThatContainsInOrder helperClasses, [
|
|
TestHelperClasses.HelperSuperClass.name,
|
|
TestHelperClasses.Helper.name
|
|
]
|
|
assertThatContainsInOrder helperClasses, [
|
|
OtherTestHelperClasses.TestEnum.name,
|
|
OtherTestHelperClasses.TestEnum.name + '$1',
|
|
]
|
|
new HashSet<>(helperClasses) == new HashSet([
|
|
TestHelperClasses.HelperSuperClass.name,
|
|
TestHelperClasses.HelperInterface.name,
|
|
TestHelperClasses.Helper.name,
|
|
OtherTestHelperClasses.Bar.name,
|
|
OtherTestHelperClasses.Foo.name,
|
|
OtherTestHelperClasses.TestEnum.name,
|
|
OtherTestHelperClasses.TestEnum.name + '$1',
|
|
OtherTestHelperClasses.name + '$1',
|
|
])
|
|
}
|
|
|
|
private static assertHelperSuperClassMethod(Reference reference, boolean isAbstract) {
|
|
assertMethod reference, 'abstractMethod', '()I',
|
|
VisibilityFlag.PROTECTED,
|
|
OwnershipFlag.NON_STATIC,
|
|
isAbstract ? ManifestationFlag.ABSTRACT : ManifestationFlag.NON_FINAL
|
|
}
|
|
|
|
private static assertHelperInterfaceMethod(Reference reference, boolean isAbstract) {
|
|
assertMethod reference, 'foo', '()V',
|
|
VisibilityFlag.PUBLIC,
|
|
OwnershipFlag.NON_STATIC,
|
|
isAbstract ? ManifestationFlag.ABSTRACT : ManifestationFlag.NON_FINAL
|
|
}
|
|
|
|
private static assertMethod(Reference reference, String methodName, String methodDesc, Reference.Flag... flags) {
|
|
def method = findMethod reference, methodName, methodDesc
|
|
method != null && (method.flags == flags as Set)
|
|
}
|
|
|
|
private static findMethod(Reference reference, String methodName, String methodDesc) {
|
|
for (def method : reference.methods) {
|
|
if (method == new Reference.Method(methodName, methodDesc)) {
|
|
return method
|
|
}
|
|
}
|
|
return null
|
|
}
|
|
|
|
private static assertField(Reference reference, String fieldName, Reference.Flag... flags) {
|
|
def field = findField reference, fieldName
|
|
field != null && (field.flags == flags as Set)
|
|
}
|
|
|
|
private static Reference.Field findField(Reference reference, String fieldName) {
|
|
for (def field : reference.fields) {
|
|
if (field.name == fieldName) {
|
|
return field
|
|
}
|
|
}
|
|
return null
|
|
}
|
|
|
|
private static assertThatContainsInOrder(List<String> list, List<String> sublist) {
|
|
def listIt = list.iterator()
|
|
def sublistIt = sublist.iterator()
|
|
while (listIt.hasNext() && sublistIt.hasNext()) {
|
|
def sublistElem = sublistIt.next()
|
|
while (listIt.hasNext()) {
|
|
def listElem = listIt.next()
|
|
if (listElem == sublistElem) {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
return !sublistIt.hasNext()
|
|
}
|
|
}
|