Add unit tests for matchers
ADD
dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/bytebuddy/matcher/HasSuperMethodMatcherTest.groovy
+package datadog.trace.agent.tooling.bytebuddy.matcher
+
+import datadog.trace.agent.tooling.bytebuddy.matcher.testclasses.A
+import datadog.trace.agent.tooling.bytebuddy.matcher.testclasses.B
+import datadog.trace.agent.tooling.bytebuddy.matcher.testclasses.C
+import datadog.trace.agent.tooling.bytebuddy.matcher.testclasses.F
+import datadog.trace.agent.tooling.bytebuddy.matcher.testclasses.G
+import datadog.trace.agent.tooling.bytebuddy.matcher.testclasses.TracedClass
+import datadog.trace.agent.tooling.bytebuddy.matcher.testclasses.UntracedClass
+import datadog.trace.api.Trace
+import datadog.trace.util.test.DDSpecification
+import net.bytebuddy.description.method.MethodDescription
+
+import static datadog.trace.agent.tooling.bytebuddy.matcher.DDElementMatchers.hasSuperMethod
+import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith
+import static net.bytebuddy.matcher.ElementMatchers.none
+
+class HasSuperMethodMatcherTest extends DDSpecification {
+
+ def "test matcher #type.simpleName #method"() {
+ expect:
+ hasSuperMethod(isAnnotatedWith(Trace)).matches(argument) == result
+
+ where:
+ type | method | result
+ A | "a" | false
+ B | "b" | true
+ C | "c" | false
+ F | "f" | true
+ G | "g" | false
+ TracedClass | "a" | true
+ UntracedClass | "a" | false
+ UntracedClass | "b" | true
+
+ argument = new MethodDescription.ForLoadedMethod(type.getDeclaredMethod(method))
+ }
+
+ def "test constructor never matches"() {
+ setup:
+ def method = Mock(MethodDescription)
+ def matcher = hasSuperMethod(none())
+
+ when:
+ def result = matcher.matches(method)
+
+ then:
+ !result
+ 1 * method.isConstructor() >> true
+ 0 * _
+ }
+
+ def "test traversal exceptions"() {
+ setup:
+ def method = Mock(MethodDescription)
+ def matcher = hasSuperMethod(none())
+ def sigToken = new MethodDescription.ForLoadedMethod(A.getDeclaredMethod("a")).asSignatureToken()
+
+ when:
+ def result = matcher.matches(method)
+
+ then:
+ !result // default to false
+ 1 * method.isConstructor() >> false
+ 1 * method.asSignatureToken() >> sigToken
+ 1 * method.getDeclaringType() >> null
+ 0 * _
+ }
+}

ADD
dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/bytebuddy/matcher/SafeExtendsClassMatcherTest.groovy
+package datadog.trace.agent.tooling.bytebuddy.matcher
+
+import datadog.trace.agent.tooling.bytebuddy.matcher.testclasses.A
+import datadog.trace.agent.tooling.bytebuddy.matcher.testclasses.B
+import datadog.trace.agent.tooling.bytebuddy.matcher.testclasses.F
+import datadog.trace.agent.tooling.bytebuddy.matcher.testclasses.G
+import datadog.trace.util.test.DDSpecification
+import net.bytebuddy.description.type.TypeDescription
+
+import static datadog.trace.agent.tooling.bytebuddy.matcher.DDElementMatchers.extendsClass
+import static net.bytebuddy.matcher.ElementMatchers.named
+
+class SafeExtendsClassMatcherTest extends DDSpecification {
+
+ def "test matcher #matcherClass.simpleName -> #type.simpleName"() {
+ expect:
+ extendsClass(matcher).matches(argument) == result
+
+ where:
+ matcherClass | type | result
+ A | B | false
+ A | F | false
+ G | F | false
+ F | F | true
+ F | G | true
+
+ matcher = named(matcherClass.name)
+ argument = TypeDescription.ForLoadedType.of(type)
+ }
+
+ def "test traversal exceptions"() {
+ setup:
+ def type = Mock(TypeDescription)
+ def typeGeneric = Mock(TypeDescription.Generic)
+ def matcher = extendsClass(named(Object.name))
+
+ when:
+ def result = matcher.matches(type)
+
+ then:
+ !result // default to false
+ noExceptionThrown()
+ 1 * type.asGenericType() >> typeGeneric
+ 1 * type.getTypeName() >> "type-name"
+ 1 * typeGeneric.asErasure() >> { throw new Exception("asErasure exception") }
+ 1 * typeGeneric.getTypeName() >> "typeGeneric-name"
+ 1 * type.getSuperClass() >> { throw new Exception("getSuperClass exception") }
+ 0 * _
+ }
+}

ADD
dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/bytebuddy/matcher/SafeHasInterfaceMatcherTest.groovy
+package datadog.trace.agent.tooling.bytebuddy.matcher
+
+import datadog.trace.agent.tooling.bytebuddy.matcher.testclasses.A
+import datadog.trace.agent.tooling.bytebuddy.matcher.testclasses.B
+import datadog.trace.agent.tooling.bytebuddy.matcher.testclasses.E
+import datadog.trace.agent.tooling.bytebuddy.matcher.testclasses.F
+import datadog.trace.agent.tooling.bytebuddy.matcher.testclasses.G
+import datadog.trace.util.test.DDSpecification
+import net.bytebuddy.description.type.TypeDescription
+
+import static datadog.trace.agent.tooling.bytebuddy.matcher.DDElementMatchers.hasInterface
+import static net.bytebuddy.matcher.ElementMatchers.named
+
+class SafeHasInterfaceMatcherTest extends DDSpecification {
+
+ def "test matcher #matcherClass.simpleName -> #type.simpleName"() {
+ expect:
+ hasInterface(matcher).matches(argument) == result
+
+ where:
+ matcherClass | type | result
+ A | A | true
+ A | B | true
+ B | A | false
+ A | E | true
+ A | F | true
+ F | A | false
+ F | F | false
+ F | G | false
+
+ matcher = named(matcherClass.name)
+ argument = TypeDescription.ForLoadedType.of(type)
+ }
+
+ def "test traversal exceptions"() {
+ setup:
+ def type = Mock(TypeDescription)
+ def typeGeneric = Mock(TypeDescription.Generic)
+ def matcher = hasInterface(named(Object.name))
+
+ when:
+ def result = matcher.matches(type)
+
+ then:
+ !result // default to false
+ noExceptionThrown()
+ 1 * type.isInterface() >> true
+ 1 * type.asGenericType() >> typeGeneric
+ 1 * typeGeneric.asErasure() >> { throw new Exception("asErasure exception") }
+ 1 * typeGeneric.getTypeName() >> "typeGeneric-name"
+ 1 * type.getInterfaces() >> { throw new Exception("getInterfaces exception") }
+ 1 * type.getSuperClass() >> { throw new Exception("getSuperClass exception") }
+ 2 * type.getTypeName() >> "type-name"
+ 0 * _
+ }
+}

ADD
dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/bytebuddy/matcher/SafeHasSuperTypeMatcherTest.groovy
+package datadog.trace.agent.tooling.bytebuddy.matcher
+
+import datadog.trace.agent.tooling.bytebuddy.matcher.testclasses.A
+import datadog.trace.agent.tooling.bytebuddy.matcher.testclasses.B
+import datadog.trace.agent.tooling.bytebuddy.matcher.testclasses.E
+import datadog.trace.agent.tooling.bytebuddy.matcher.testclasses.F
+import datadog.trace.agent.tooling.bytebuddy.matcher.testclasses.G
+import datadog.trace.util.test.DDSpecification
+import net.bytebuddy.description.type.TypeDescription
+
+import static datadog.trace.agent.tooling.bytebuddy.matcher.DDElementMatchers.safeHasSuperType
+import static net.bytebuddy.matcher.ElementMatchers.named
+
+class SafeHasSuperTypeMatcherTest extends DDSpecification {
+
+ def "test matcher #matcherClass.simpleName -> #type.simpleName"() {
+ expect:
+ safeHasSuperType(matcher).matches(argument) == result
+
+ where:
+ matcherClass | type | result
+ A | A | true
+ A | B | true
+ B | A | false
+ A | E | true
+ A | F | true
+ F | A | false
+ F | F | true
+ F | G | true
+
+ matcher = named(matcherClass.name)
+ argument = TypeDescription.ForLoadedType.of(type)
+ }
+
+ def "test traversal exceptions"() {
+ setup:
+ def type = Mock(TypeDescription)
+ def typeGeneric = Mock(TypeDescription.Generic)
+ def matcher = safeHasSuperType(named(Object.name))
+
+ when:
+ def result = matcher.matches(type)
+
+ then:
+ !result // default to false
+ noExceptionThrown()
+ 1 * type.asGenericType() >> typeGeneric
+ 1 * typeGeneric.asErasure() >> { throw new Exception("asErasure exception") }
+ 1 * typeGeneric.getTypeName() >> "typeGeneric-name"
+ 1 * type.getInterfaces() >> { throw new Exception("getInterfaces exception") }
+ 1 * type.getSuperClass() >> { throw new Exception("getSuperClass exception") }
+ 2 * type.getTypeName() >> "type-name"
+ 0 * _
+ }
+}

ADD
dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/bytebuddy/matcher/SafeMatcherTest.groovy
+package datadog.trace.agent.tooling.bytebuddy.matcher
+
+import datadog.trace.util.test.DDSpecification
+import net.bytebuddy.matcher.ElementMatcher
+
+import static datadog.trace.agent.tooling.bytebuddy.matcher.DDElementMatchers.failSafe
+
+class SafeMatcherTest extends DDSpecification {
+
+ def mockMatcher = Mock(ElementMatcher)
+
+ def "test matcher"() {
+ setup:
+ def matcher = failSafe(mockMatcher, "test")
+
+ when:
+ def result = matcher.matches(new Object())
+
+ then:
+ 1 * mockMatcher.matches(_) >> match
+ result == match
+
+ where:
+ match << [true, false]
+ }
+
+ def "test matcher exception"() {
+ setup:
+ def matcher = failSafe(mockMatcher, "test")
+
+ when:
+ def result = matcher.matches(new Object())
+
+ then:
+ 1 * mockMatcher.matches(_) >> { throw new Exception("matcher exception") }
+ 0 * _
+ noExceptionThrown()
+ !result // default to false
+ }
+}

ADD
dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/bytebuddy/matcher/testclasses/A.java
+package datadog.trace.agent.tooling.bytebuddy.matcher.testclasses;
+
+public interface A {
+ void a();
+}

ADD
dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/bytebuddy/matcher/testclasses/B.java
+package datadog.trace.agent.tooling.bytebuddy.matcher.testclasses;
+
+import datadog.trace.api.Trace;
+
+public interface B extends A {
+ @Trace
+ void b();
+}

ADD
dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/bytebuddy/matcher/testclasses/C.java
+package datadog.trace.agent.tooling.bytebuddy.matcher.testclasses;
+
+public interface C extends A, B {
+ void c();
+}

ADD
dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/bytebuddy/matcher/testclasses/D.java
+package datadog.trace.agent.tooling.bytebuddy.matcher.testclasses;
+
+import datadog.trace.api.Trace;
+
+public interface D extends A, B, C {
+ @Trace
+ void d();
+}

ADD
dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/bytebuddy/matcher/testclasses/E.java
+package datadog.trace.agent.tooling.bytebuddy.matcher.testclasses;
+
+public interface E extends B, C, D {
+ void e();
+}

ADD
dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/bytebuddy/matcher/testclasses/F.java
+package datadog.trace.agent.tooling.bytebuddy.matcher.testclasses;
+
+import datadog.trace.api.Trace;
+
+public abstract class F implements E {
+ @Trace
+ public abstract void f();
+}

ADD
dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/bytebuddy/matcher/testclasses/G.java
+package datadog.trace.agent.tooling.bytebuddy.matcher.testclasses;
+
+public abstract class G extends F {
+ public void g() {}
+}

ADD
dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/bytebuddy/matcher/testclasses/TracedClass.java
+package datadog.trace.agent.tooling.bytebuddy.matcher.testclasses;
+
+import datadog.trace.api.Trace;
+
+public class TracedClass extends UntracedClass {
+ @Trace
+ @Override
+ public void g() {}
+
+ @Trace
+ @Override
+ public void f() {}
+
+ @Trace
+ @Override
+ public void e() {}
+
+ @Trace
+ @Override
+ public void d() {}
+
+ @Trace
+ @Override
+ public void c() {}
+
+ @Trace
+ @Override
+ public void b() {}
+
+ @Trace
+ @Override
+ public void a() {}
+}

ADD
dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/bytebuddy/matcher/testclasses/UntracedClass.java
+package datadog.trace.agent.tooling.bytebuddy.matcher.testclasses;
+
+public class UntracedClass extends G {
+ @Override
+ public void g() {}
+
+ @Override
+ public void f() {}
+
+ @Override
+ public void e() {}
+
+ @Override
+ public void d() {}
+
+ @Override
+ public void c() {}
+
+ @Override
+ public void b() {}
+
+ @Override
+ public void a() {}
+}

Add unit tests for matchers