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 extends TypeElement> annotations, RoundEnvironment roundEnv) {
- createTestableAgentJar();
+ if (cx.names == null) {
+ return true;
+ }
Set extends Element> 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