From 3bf9e1a623dff5304e48218c23c6eba19fc4fe6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=87=91=E6=88=9F?= Date: Wed, 14 Oct 2020 20:18:45 +0800 Subject: [PATCH] move agent jar to class folder and bump version to v0.1.0-snapshot --- agent/pom.xml | 2 +- core/pom.xml | 2 +- .../testable/core/model/TestableContext.java | 10 +++ .../core/processor/BaseProcessor.java | 30 ------- .../processor/EnableTestableProcessor.java | 84 +++++++++++++------ .../testable/core/util/ResourceUtil.java | 3 +- docs/ReleaseNote.md | 28 ++++--- 7 files changed, 87 insertions(+), 72 deletions(-) delete mode 100644 core/src/main/java/com/alibaba/testable/core/processor/BaseProcessor.java diff --git a/agent/pom.xml b/agent/pom.xml index 7b1339e..e0dd246 100755 --- a/agent/pom.xml +++ b/agent/pom.xml @@ -5,7 +5,7 @@ com.alibaba.testable agent - 0.0.5-SNAPSHOT + 0.1.0-SNAPSHOT jar diff --git a/core/pom.xml b/core/pom.xml index 4e710b4..d034070 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -8,7 +8,7 @@ Unit test enhancement toolkit com.alibaba.testable core - 0.0.5-SNAPSHOT + 0.1.0-SNAPSHOT 3.8.1 diff --git a/core/src/main/java/com/alibaba/testable/core/model/TestableContext.java b/core/src/main/java/com/alibaba/testable/core/model/TestableContext.java index 85158cf..2a77bc9 100644 --- a/core/src/main/java/com/alibaba/testable/core/model/TestableContext.java +++ b/core/src/main/java/com/alibaba/testable/core/model/TestableContext.java @@ -60,4 +60,14 @@ public class TestableContext { this.names = names; } + public TestableContext(TestableLogger logger, Filer filter) { + this.logger = logger; + this.filter = filter; + this.elementUtils = null; + this.typeUtils = null; + this.trees = null; + this.treeMaker = null; + this.names = null; + } + } diff --git a/core/src/main/java/com/alibaba/testable/core/processor/BaseProcessor.java b/core/src/main/java/com/alibaba/testable/core/processor/BaseProcessor.java deleted file mode 100644 index a08e508..0000000 --- a/core/src/main/java/com/alibaba/testable/core/processor/BaseProcessor.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.alibaba.testable.core.processor; - -import com.alibaba.testable.core.model.TestableContext; -import com.alibaba.testable.core.util.TestableLogger; -import com.sun.tools.javac.api.JavacTrees; -import com.sun.tools.javac.processing.JavacProcessingEnvironment; -import com.sun.tools.javac.tree.TreeMaker; -import com.sun.tools.javac.util.Context; -import com.sun.tools.javac.util.Names; - -import javax.annotation.processing.AbstractProcessor; -import javax.annotation.processing.ProcessingEnvironment; - -/** - * @author flin - */ -public abstract class BaseProcessor extends AbstractProcessor { - - protected TestableContext cx; - - @Override - public synchronized void init(ProcessingEnvironment processingEnv) { - super.init(processingEnv); - Context context = ((JavacProcessingEnvironment)processingEnv).getContext(); - cx = new TestableContext(new TestableLogger(processingEnv.getMessager()), processingEnv.getFiler(), - processingEnv.getElementUtils(), processingEnv.getTypeUtils(), JavacTrees.instance(processingEnv), - TreeMaker.instance(context), Names.instance(context)); - } - -} diff --git a/core/src/main/java/com/alibaba/testable/core/processor/EnableTestableProcessor.java b/core/src/main/java/com/alibaba/testable/core/processor/EnableTestableProcessor.java index 61ebad9..0361149 100644 --- a/core/src/main/java/com/alibaba/testable/core/processor/EnableTestableProcessor.java +++ b/core/src/main/java/com/alibaba/testable/core/processor/EnableTestableProcessor.java @@ -1,15 +1,20 @@ package com.alibaba.testable.core.processor; import com.alibaba.testable.core.annotation.EnableTestable; -import com.alibaba.testable.core.translator.EnableTestableTranslator; import com.alibaba.testable.core.constant.ConstPool; +import com.alibaba.testable.core.model.TestableContext; +import com.alibaba.testable.core.translator.EnableTestableTranslator; import com.alibaba.testable.core.util.ResourceUtil; +import com.alibaba.testable.core.util.TestableLogger; +import com.sun.tools.javac.api.JavacTrees; import com.sun.tools.javac.code.Symbol; +import com.sun.tools.javac.processing.JavacProcessingEnvironment; import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.TreeMaker; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.Names; -import javax.annotation.processing.RoundEnvironment; -import javax.annotation.processing.SupportedAnnotationTypes; -import javax.annotation.processing.SupportedSourceVersion; +import javax.annotation.processing.*; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; import javax.lang.model.element.Name; @@ -24,15 +29,41 @@ import java.util.Set; * @author flin */ @SupportedAnnotationTypes("com.alibaba.testable.core.annotation.EnableTestable") -@SupportedSourceVersion(SourceVersion.RELEASE_7) -public class EnableTestableProcessor extends BaseProcessor { +public class EnableTestableProcessor extends AbstractProcessor { private static final String TESTABLE_AGENT_JAR = "testable-agent.jar"; - private static boolean hasFirstClassCompiled = false; + private static final String TEST_OUTPUT_FOLDER_MARK = "/test-classes/"; + private TestableContext cx; + + @Override + public synchronized void init(ProcessingEnvironment processingEnv) { + super.init(processingEnv); + Context context = getJavacProcessingContext(processingEnv); + if (context == null) { + cx = new TestableContext(new TestableLogger(processingEnv.getMessager()), processingEnv.getFiler()); + cx.logger.info("Skip testable compile time processing"); + } else { + cx = new TestableContext(new TestableLogger(processingEnv.getMessager()), processingEnv.getFiler(), + processingEnv.getElementUtils(), processingEnv.getTypeUtils(), JavacTrees.instance(processingEnv), + TreeMaker.instance(context), Names.instance(context)); + } + createTestableAgentJar(); + cx.logger.info("Testable processor initialized"); + } + + private Context getJavacProcessingContext(ProcessingEnvironment processingEnv) { + try { + return ((JavacProcessingEnvironment)processingEnv).getContext(); + } catch (Exception e) { + return null; + } + } @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { - createTestableAgentJar(); + if (cx.names == null) { + return true; + } Set elements = roundEnv.getElementsAnnotatedWith(EnableTestable.class); for (Element element : elements) { if (element.getKind().isClass() && isTestClass(element.getSimpleName())) { @@ -42,40 +73,41 @@ public class EnableTestableProcessor extends BaseProcessor { return true; } + @Override + public SourceVersion getSupportedSourceVersion() { + // always return the latest version + return SourceVersion.values()[SourceVersion.values().length - 1]; + } + private boolean isTestClass(Name name) { return name.toString().endsWith(ConstPool.TEST_POSTFIX); } private void processClassElement(Symbol.ClassSymbol clazz) { JCTree tree = cx.trees.getTree(clazz); - tree.accept(new EnableTestableTranslator(getPkgName(clazz), clazz.getSimpleName().toString(), cx)); - } - - private String getPkgName(Symbol.ClassSymbol clazz) { - return ((Symbol.PackageSymbol)clazz.owner).fullname.toString(); + String pkgName = ((Symbol.PackageSymbol)clazz.owner).fullname.toString(); + tree.accept(new EnableTestableTranslator(pkgName, clazz.getSimpleName().toString(), cx)); } private void createTestableAgentJar() { - if (!hasFirstClassCompiled) { - hasFirstClassCompiled = true; - byte[] bytes = ResourceUtil.fetchBinary(TESTABLE_AGENT_JAR); - if (bytes.length == 0) { - cx.logger.error("Failed to generate testable agent jar"); - } - writeBinaryFile("", TESTABLE_AGENT_JAR, bytes); + byte[] bytes = ResourceUtil.fetchBinary(TESTABLE_AGENT_JAR); + if (bytes.length == 0) { + cx.logger.info("Failed to fetch testable agent jar"); } - } - - private void writeBinaryFile(String path, String fileName, byte[] content) { try { - FileObject resource = cx.filter.createResource(StandardLocation.SOURCE_OUTPUT, path, fileName); + FileObject resource = cx.filter.createResource(StandardLocation.CLASS_OUTPUT, "", TESTABLE_AGENT_JAR); + if (!resource.getName().contains(TEST_OUTPUT_FOLDER_MARK)) { + cx.logger.info("Skip generate testable agent jar"); + return; + } + cx.logger.info("Generating " + resource.getName()); try (OutputStream out = resource.openOutputStream()) { - out.write(content); + out.write(bytes); out.flush(); } } catch (IOException e) { e.printStackTrace(); - cx.logger.error("Failed to write " + fileName); + cx.logger.error("Failed to generate testable agent jar"); } } } diff --git a/core/src/main/java/com/alibaba/testable/core/util/ResourceUtil.java b/core/src/main/java/com/alibaba/testable/core/util/ResourceUtil.java index 371644c..f265d39 100644 --- a/core/src/main/java/com/alibaba/testable/core/util/ResourceUtil.java +++ b/core/src/main/java/com/alibaba/testable/core/util/ResourceUtil.java @@ -13,8 +13,7 @@ public class ResourceUtil { StringBuilder buffer = new StringBuilder(); String line; try { - while ((line = reader.readLine()) != null) - { + while ((line = reader.readLine()) != null) { buffer.append(line).append('\n'); } reader.close(); diff --git a/docs/ReleaseNote.md b/docs/ReleaseNote.md index 9c0927a..cbf6264 100644 --- a/docs/ReleaseNote.md +++ b/docs/ReleaseNote.md @@ -1,22 +1,26 @@ # Release Note -## v0.0.1 -- PoC version -- use compile time code modification to support new operation mocking and private field & method access +## v0.1.0 +- move generated agent jar to class folder +- now support mock method of any object -## v0.0.2 -- add support of member method mocking by compile time code modification +## v0.0.5 +- use dynamically runtime modification to replace static `e.java` file +- get rid of unit test framework dependence +- add testable ref field in test class at runtime instead of compile time + +## v0.0.4 +- use runtime byte code rewrite to invoke testable setup method +- add `TestableUtil` class to fetch current test case and invocation source ## v0.0.3 - use global method invoke to access private members instead of modification in place - use `e.java` replace `testable` class make code more readable - introduce `agent` module, use runtime byte code modification to support new operation and member method mocking -## v0.0.4 -- use runtime byte code rewrite to invoke testable setup method -- add `TestableUtil` class to fetch current test case and invocation source +## v0.0.2 +- add support of member method mocking by compile time code modification -## v0.0.5 -- use dynamically runtime modification to replace static `e.java` file -- get rid of unit test framework dependence -- add testable ref field in test class at runtime instead of compile time +## v0.0.1 +- PoC version +- use compile time code modification to support new operation mocking and private field & method access