mirror of
https://github.com/alibaba/testable-mock.git
synced 2025-03-13 11:20:32 +08:00
move agent jar to class folder and bump version to v0.1.0-snapshot
This commit is contained in:
parent
c869caa0c9
commit
3bf9e1a623
@ -5,7 +5,7 @@
|
||||
|
||||
<groupId>com.alibaba.testable</groupId>
|
||||
<artifactId>agent</artifactId>
|
||||
<version>0.0.5-SNAPSHOT</version>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
|
@ -8,7 +8,7 @@
|
||||
<description>Unit test enhancement toolkit</description>
|
||||
<groupId>com.alibaba.testable</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
<version>0.0.5-SNAPSHOT</version>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<plugin.compiler.version>3.8.1</plugin.compiler.version>
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user