![JAR search and dependency download from the Maven repository](/logo.png)
com.undefinedlabs.scope.rules.JUnit4ScopeRunnerAgentRule Maven / Gradle / Ivy
package com.undefinedlabs.scope.rules;
import com.undefinedlabs.scope.ScopeGlobalTracer;
import com.undefinedlabs.scope.deps.org.apache.commons.lang3.reflect.MethodUtils;
import com.undefinedlabs.scope.rules.model.JUnit4ScopeFrameworkMethod;
import com.undefinedlabs.scope.rules.transformer.ScopeAgentAdvicedTransformer;
import com.undefinedlabs.scope.runner.ScopeGlobalRunner;
import com.undefinedlabs.scope.runner.ScopeRunner;
import com.undefinedlabs.scope.runner.TestStatus;
import com.undefinedlabs.scope.runner.rules.AbstractScopeRunnerAgentRule;
import com.undefinedlabs.scope.settings.ScopeSettings;
import com.undefinedlabs.scope.settings.ScopeSettingsResolver;
import com.undefinedlabs.scope.statistics.Statistics;
import com.undefinedlabs.scope.utils.SpanUtils;
import com.undefinedlabs.scope.utils.baggage.BaggageKeys;
import com.undefinedlabs.scope.utils.baggage.BaggageValues;
import com.undefinedlabs.scope.utils.tag.TagKeys;
import com.undefinedlabs.scope.utils.tag.TagValues;
import io.opentracing.Span;
import io.opentracing.Tracer;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.asm.Advice;
import org.junit.Test;
import org.junit.internal.builders.IgnoredClassRunner;
import org.junit.runners.model.FrameworkMethod;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static net.bytebuddy.implementation.bytecode.assign.Assigner.Typing.DYNAMIC;
import static net.bytebuddy.matcher.ElementMatchers.isSystemClassLoader;
import static net.bytebuddy.matcher.ElementMatchers.named;
public class JUnit4ScopeRunnerAgentRule extends AbstractScopeRunnerAgentRule {
@Override
protected Iterable extends AgentBuilder> transformers() {
return Collections.singleton(newAgentBuilder()
.type(named("org.junit.runners.BlockJUnit4ClassRunner"), isSystemClassLoader()).transform(new ScopeAgentAdvicedTransformer(JUnit4RunnerAdvice.class, named("getChildren")))
.type(named("org.junit.internal.builders.IgnoredClassRunner"), isSystemClassLoader()).transform(new ScopeAgentAdvicedTransformer(IgnoredClassRunnerAdvice.class, named("run")))
);
}
public static class JUnit4RunnerAdvice {
@Advice.OnMethodExit
public static void exit(@Advice.This Object runnerObj, @Advice.AllArguments Object[] args, @Advice.Return(readOnly = false, typing = DYNAMIC) Object returnObj) {
final ScopeRunner runner = ScopeGlobalRunner.get();
final List tests = (List) returnObj;
final List finalTests = new ArrayList<>();
final Tracer tracer = ScopeGlobalTracer.get();
final ScopeSettings settings = ScopeSettingsResolver.INSTANCE.get();
for(final FrameworkMethod test : tests) {
final JUnit4ScopeFrameworkMethod scopeTest = new JUnit4ScopeFrameworkMethod(test);
if(!runner.getTestStatuses(scopeTest.getTestSuite(), scopeTest.getTestName()).contains(TestStatus.CACHED)) {
finalTests.add(test);
} else {
if((boolean)settings.getSetting(ScopeSettings.SCOPE_RUNNER_SEND_SPANS)) {
final Span span = tracer.buildSpan(scopeTest.getTestName())
.ignoreActiveSpan()
.withTag(TagKeys.COMPONENT, TagValues.Test.Framework.JUNIT_4)
.withTag(TagKeys.SPAN_KIND, TagValues.SPAN_KIND_TEST)
.withTag(TagKeys.Test.TEST_NAME, scopeTest.getTestName())
.withTag(TagKeys.Test.TEST_SUITE, scopeTest.getTestSuite())
.withTag(TagKeys.Test.TEST_FRAMEWORK, TagValues.Test.Framework.JUNIT_4)
.withTag(TagKeys.Test.TEST_LANGUAGE, TagValues.Test.Language.JAVA)
.withTag(TagKeys.Test.TEST_STATUS, TagValues.Test.TEST_CACHE)
.withTag(TagKeys.ERROR, false)
.start();
span.setBaggageItem(BaggageKeys.TRACE_KIND, BaggageValues.TRACE_KIND_TEST);
span.finish(SpanUtils.INSTANCE.getStartTimestampMicros(span));
}
Statistics.INSTANCE.registerRunnerCachedTest(TagValues.Test.Framework.JUNIT_4, scopeTest.getTestSuite(), scopeTest.getTestName());
}
}
returnObj = finalTests;
}
}
private static Class findTestClassFromIgnoredClassRunner(final Object runnerObj, final String fieldName) {
try {
final IgnoredClassRunner junitRunner = (IgnoredClassRunner) runnerObj;
final Field fTestClassField = junitRunner.getClass().getDeclaredField(fieldName);
fTestClassField.setAccessible(true);
return (Class>) fTestClassField.get(junitRunner);
} catch (Exception e) {
return null;
}
}
public static Class findTestClassFromIgnoredClassRunner(final Object runnerObj) {
final Class testClass = findTestClassFromIgnoredClassRunner(runnerObj, "clazz");
if(testClass == null) {
return findTestClassFromIgnoredClassRunner(runnerObj, "fTestClass");
}
return testClass;
}
public static class IgnoredClassRunnerAdvice {
@Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class)
public static Object enter(@Advice.This Object runnerObj) {
try {
final Class> fTestClass = JUnit4ScopeRunnerAgentRule.findTestClassFromIgnoredClassRunner(runnerObj);
if(fTestClass == null) {
return null;
}
final List testMethods = MethodUtils.getMethodsListWithAnnotation(fTestClass, Test.class);
boolean hasCachedTests = false;
final ScopeRunner scopeRunner = ScopeGlobalRunner.get();
for (int i = 0; i < testMethods.size() && !hasCachedTests; i++) {
final Method testMethod = testMethods.get(i);
hasCachedTests = scopeRunner.getTestStatuses(fTestClass.getName(), testMethod.getName()).contains(TestStatus.CACHED);
}
if (hasCachedTests) {
final Tracer tracer = ScopeGlobalTracer.get();
for (final Method testMethod : testMethods) {
final Span span = tracer.buildSpan(testMethod.getName())
.ignoreActiveSpan()
.withTag(TagKeys.COMPONENT, TagValues.Test.Framework.JUNIT_4)
.withTag(TagKeys.SPAN_KIND, TagValues.SPAN_KIND_TEST)
.withTag(TagKeys.Test.TEST_NAME, fTestClass.getName())
.withTag(TagKeys.Test.TEST_SUITE, testMethod.getName())
.withTag(TagKeys.Test.TEST_FRAMEWORK, TagValues.Test.Framework.JUNIT_4)
.withTag(TagKeys.Test.TEST_LANGUAGE, TagValues.Test.Language.JAVA)
.withTag(TagKeys.Test.TEST_STATUS, TagValues.Test.TEST_CACHE)
.withTag(TagKeys.ERROR, false)
.start();
span.setBaggageItem(BaggageKeys.TRACE_KIND, BaggageValues.TRACE_KIND_TEST);
span.finish(SpanUtils.INSTANCE.getStartTimestampMicros(span));
Statistics.INSTANCE.registerRunnerCachedTest("Junit4", fTestClass.getName(), testMethod.getName());
}
return new Object();
}
return null;
} catch (Exception e) {
return null;
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy