diff --git a/testable-agent/src/main/java/com/alibaba/testable/agent/handler/MockClassHandler.java b/testable-agent/src/main/java/com/alibaba/testable/agent/handler/MockClassHandler.java index 7a05b5e..aedeedc 100644 --- a/testable-agent/src/main/java/com/alibaba/testable/agent/handler/MockClassHandler.java +++ b/testable-agent/src/main/java/com/alibaba/testable/agent/handler/MockClassHandler.java @@ -42,6 +42,7 @@ public class MockClassHandler extends BaseClassWithContextHandler { @Override protected void transform(ClassNode cn) { + LogUtil.diagnose("Found mock class %s", cn.name); if (!CLASS_OBJECT.equals(cn.superName)) { MockAssociationUtil.recordSubMockContainer(ClassUtil.toDotSeparatedName(cn.superName), ClassUtil.toDotSeparatedName(cn.name)); diff --git a/testable-agent/src/main/java/com/alibaba/testable/agent/handler/SourceClassHandler.java b/testable-agent/src/main/java/com/alibaba/testable/agent/handler/SourceClassHandler.java index 2cf88d1..348ad11 100644 --- a/testable-agent/src/main/java/com/alibaba/testable/agent/handler/SourceClassHandler.java +++ b/testable-agent/src/main/java/com/alibaba/testable/agent/handler/SourceClassHandler.java @@ -41,6 +41,7 @@ public class SourceClassHandler extends BaseClassHandler { */ @Override protected void transform(ClassNode cn) { + LogUtil.diagnose("Found source class %s", cn.name); Set memberInjectMethods = new HashSet(); Set newOperatorInjectMethods = new HashSet(); for (MethodInfo im : injectMethods) { diff --git a/testable-agent/src/main/java/com/alibaba/testable/agent/handler/TestClassHandler.java b/testable-agent/src/main/java/com/alibaba/testable/agent/handler/TestClassHandler.java index d641568..15a6ed0 100644 --- a/testable-agent/src/main/java/com/alibaba/testable/agent/handler/TestClassHandler.java +++ b/testable-agent/src/main/java/com/alibaba/testable/agent/handler/TestClassHandler.java @@ -1,12 +1,12 @@ package com.alibaba.testable.agent.handler; -import com.alibaba.testable.agent.handler.test.*; +import com.alibaba.testable.agent.handler.test.Framework; import com.alibaba.testable.agent.model.TestCaseMethodType; import com.alibaba.testable.core.util.LogUtil; -import org.objectweb.asm.tree.*; - -import java.util.HashSet; -import java.util.Set; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.InsnList; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.MethodNode; /** * @author flin @@ -20,14 +20,11 @@ public class TestClassHandler extends BaseClassWithContextHandler { private int testCaseCount = 0; private boolean shouldGenerateCleanupMethod = true; + private final Framework framework; - private final Framework[] frameworkClasses = new Framework[] { - new JUnit4Framework(), - new JUnit5Framework(), - new TestNgFramework(), - new TestNgOnClassFramework(), - new SpockFramework() - }; + public TestClassHandler(Framework framework) { + this.framework = framework; + } /** * Handle bytecode of test class @@ -35,11 +32,7 @@ public class TestClassHandler extends BaseClassWithContextHandler { */ @Override protected void transform(ClassNode cn) { - Framework framework = checkFramework(cn); - if (framework == null) { - LogUtil.warn("Failed to detect test framework for %s", cn.name); - return; - } + LogUtil.diagnose("Found test class %s", cn.name); for (MethodNode mn : cn.methods) { handleTestableUtil(mn); handleTestCaseMethod(mn, framework); @@ -52,28 +45,6 @@ public class TestClassHandler extends BaseClassWithContextHandler { LogUtil.diagnose(" Found %d test cases", testCaseCount); } - private Framework checkFramework(ClassNode cn) { - Set classAnnotationSet = new HashSet(); - Set methodAnnotationSet = new HashSet(); - if (cn.visibleAnnotations != null) { - for (AnnotationNode an : cn.visibleAnnotations) { - classAnnotationSet.add(an.desc); - } - } - for (MethodNode mn : cn.methods) { - if (mn.visibleAnnotations != null) { - for (AnnotationNode an : mn.visibleAnnotations) { - methodAnnotationSet.add(an.desc); - } - } - } - for (Framework i : frameworkClasses) { - if (i.fit(classAnnotationSet, methodAnnotationSet)) { - return i; - } - } - return null; - } private void handleTestCaseMethod(MethodNode mn, Framework framework) { TestCaseMethodType type = framework.checkMethodType(mn); diff --git a/testable-agent/src/main/java/com/alibaba/testable/agent/transformer/TestClassChecker.java b/testable-agent/src/main/java/com/alibaba/testable/agent/transformer/TestClassChecker.java new file mode 100644 index 0000000..0db379e --- /dev/null +++ b/testable-agent/src/main/java/com/alibaba/testable/agent/transformer/TestClassChecker.java @@ -0,0 +1,47 @@ +package com.alibaba.testable.agent.transformer; + +import com.alibaba.testable.agent.handler.test.*; +import org.objectweb.asm.tree.AnnotationNode; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.MethodNode; + +import java.util.HashSet; +import java.util.Set; + +/** + * @author flin + */ +public class TestClassChecker { + + private final Framework[] frameworkClasses = new Framework[] { + new JUnit4Framework(), + new JUnit5Framework(), + new TestNgFramework(), + new TestNgOnClassFramework(), + new SpockFramework() + }; + + public Framework checkFramework(ClassNode cn) { + Set classAnnotationSet = new HashSet(); + Set methodAnnotationSet = new HashSet(); + if (cn.visibleAnnotations != null) { + for (AnnotationNode an : cn.visibleAnnotations) { + classAnnotationSet.add(an.desc); + } + } + for (MethodNode mn : cn.methods) { + if (mn.visibleAnnotations != null) { + for (AnnotationNode an : mn.visibleAnnotations) { + methodAnnotationSet.add(an.desc); + } + } + } + for (Framework i : frameworkClasses) { + if (i.fit(classAnnotationSet, methodAnnotationSet)) { + return i; + } + } + return null; + } + +} diff --git a/testable-agent/src/main/java/com/alibaba/testable/agent/transformer/TestableClassTransformer.java b/testable-agent/src/main/java/com/alibaba/testable/agent/transformer/TestableClassTransformer.java index 9bedd14..f3ac767 100644 --- a/testable-agent/src/main/java/com/alibaba/testable/agent/transformer/TestableClassTransformer.java +++ b/testable-agent/src/main/java/com/alibaba/testable/agent/transformer/TestableClassTransformer.java @@ -5,6 +5,7 @@ import com.alibaba.testable.agent.handler.MockClassHandler; import com.alibaba.testable.agent.handler.OmniClassHandler; import com.alibaba.testable.agent.handler.SourceClassHandler; import com.alibaba.testable.agent.handler.TestClassHandler; +import com.alibaba.testable.agent.handler.test.Framework; import com.alibaba.testable.agent.model.MethodInfo; import com.alibaba.testable.agent.util.*; import com.alibaba.testable.core.exception.TargetNotExistException; @@ -42,7 +43,8 @@ public class TestableClassTransformer implements ClassFileTransformer { private final String[] BLACKLIST_PREFIXES = new String[] { "sun/", "com/sun/", "javax/crypto/", "java/util/logging/", "org/gradle/", "org/robolectric/" }; - public MockClassParser mockClassParser = new MockClassParser(); + private final MockClassParser mockClassParser = new MockClassParser(); + private final TestClassChecker testClassChecker = new TestClassChecker(); @Override public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, @@ -68,23 +70,26 @@ public class TestableClassTransformer implements ClassFileTransformer { try { if (mockClassParser.isMockClass(cn)) { // it's a mock class - LogUtil.diagnose("Found mock class %s", className); bytes = new MockClassHandler(className).getBytes(bytes); BytecodeUtil.dumpByte(className, GlobalConfig.getDumpPath(), bytes); - } else if (foundMockForTestClass(className) != null) { - // it's a test class with testable enabled - LogUtil.diagnose("Found test class %s", className); - bytes = new TestClassHandler().getBytes(bytes); + return bytes; + } + String mockClass = foundMockForSourceClass(className); + if (mockClass != null) { + // it's a source class with testable enabled + List injectMethods = mockClassParser.getTestableMockMethods(mockClass); + bytes = new SourceClassHandler(injectMethods, mockClass).getBytes(bytes); BytecodeUtil.dumpByte(className, GlobalConfig.getDumpPath(), bytes); - } else { - String mockClass = foundMockForSourceClass(className); - if (mockClass != null) { - // it's a source class with testable enabled - List injectMethods = mockClassParser.getTestableMockMethods(mockClass); - LogUtil.diagnose("Found source class %s", className); - bytes = new SourceClassHandler(injectMethods, mockClass).getBytes(bytes); - BytecodeUtil.dumpByte(className, GlobalConfig.getDumpPath(), bytes); - } + return bytes; + } + Framework framework = testClassChecker.checkFramework(cn); + if (framework != null) { + // it's a test class + bytes = new TestClassHandler(framework).getBytes(bytes); + BytecodeUtil.dumpByte(className, GlobalConfig.getDumpPath(), bytes); + return bytes; + } else if (cn.name.endsWith(TEST_POSTFIX)) { + LogUtil.verbose("Failed to detect test framework for %s", cn.name); } } catch (TargetNotExistException e) { LogUtil.error("Invalid mock method %s::%s - %s", className, e.getMethodName(), e.getMessage());