add verbose log when test start

This commit is contained in:
金戟 2020-12-10 15:47:55 +08:00
parent 4def468d85
commit c8115f9623
3 changed files with 39 additions and 18 deletions

View File

@ -8,9 +8,7 @@ import com.alibaba.testable.core.tool.TestableConst;
import org.objectweb.asm.tree.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author flin
@ -24,13 +22,12 @@ public class TestClassHandler extends BaseClassHandler {
private static final String FIELD_SOURCE_METHOD = "SOURCE_METHOD";
private static final String METHOD_CURRENT_TEST_CASE_NAME = "currentTestCaseName";
private static final String METHOD_CURRENT_SOURCE_METHOD_NAME = "currentSourceMethodName";
private static final String METHOD_MARK_TEST_CASE_BEGIN = "markTestCaseBegin";
private static final String METHOD_RECORD_MOCK_INVOKE = "recordMockInvoke";
private static final String SIGNATURE_TESTABLE_UTIL_METHOD = "(Ljava/lang/Object;)Ljava/lang/String;";
private static final String SIGNATURE_CURRENT_TEST_CASE_NAME = "(Ljava/lang/Object;)Ljava/lang/String;";
private static final String SIGNATURE_CURRENT_SOURCE_METHOD_NAME = "()Ljava/lang/String;";
private static final String SIGNATURE_VOID_METHOD_WITHOUT_PARAMETER = "()V";
private static final String SIGNATURE_INVOKE_RECORDER_METHOD = "([Ljava/lang/Object;Z)V";
private static final Map<String, String> FIELD_TO_METHOD_MAPPING = new HashMap<String, String>() {{
put(FIELD_TEST_CASE, METHOD_CURRENT_TEST_CASE_NAME);
put(FIELD_SOURCE_METHOD, METHOD_CURRENT_SOURCE_METHOD_NAME);
}};
/**
* Handle bytecode of test class
@ -91,11 +88,18 @@ public class TestClassHandler extends BaseClassHandler {
private AbstractInsnNode[] replaceTestableUtilField(MethodNode mn, AbstractInsnNode[] instructions,
String fieldName, int pos) {
InsnList il = new InsnList();
il.add(new VarInsnNode(ALOAD, 0));
il.add(new MethodInsnNode(INVOKESTATIC, CLASS_TESTABLE_UTIL, FIELD_TO_METHOD_MAPPING.get(fieldName),
SIGNATURE_TESTABLE_UTIL_METHOD, false));
mn.instructions.insert(instructions[pos], il);
mn.instructions.remove(instructions[pos]);
if (FIELD_TEST_CASE.equals(fieldName)) {
il.add(new VarInsnNode(ALOAD, 0));
il.add(new MethodInsnNode(INVOKESTATIC, CLASS_TESTABLE_UTIL, METHOD_CURRENT_TEST_CASE_NAME,
SIGNATURE_CURRENT_TEST_CASE_NAME, false));
} else if (FIELD_SOURCE_METHOD.equals(fieldName)) {
il.add(new MethodInsnNode(INVOKESTATIC, CLASS_TESTABLE_UTIL, METHOD_CURRENT_SOURCE_METHOD_NAME,
SIGNATURE_CURRENT_SOURCE_METHOD_NAME, false));
}
if (il.size() > 0) {
mn.instructions.insert(instructions[pos], il);
mn.instructions.remove(instructions[pos]);
}
return mn.instructions.toArray();
}
@ -181,18 +185,24 @@ public class TestClassHandler extends BaseClassHandler {
private void injectTestableRef(ClassNode cn, MethodNode mn) {
InsnList il = new InsnList();
// Initialize "_testableInternalRef"
il.add(new VarInsnNode(ALOAD, 0));
il.add(new FieldInsnNode(PUTSTATIC, cn.name, ConstPool.TESTABLE_INJECT_REF,
ClassUtil.toByteCodeClassName(cn.name)));
mn.instructions.insertBefore(mn.instructions.get(0), il);
// Invoke "markTestCaseBegin"
il.add(new MethodInsnNode(INVOKESTATIC, CLASS_TESTABLE_UTIL, METHOD_MARK_TEST_CASE_BEGIN,
SIGNATURE_VOID_METHOD_WITHOUT_PARAMETER, false));
mn.instructions.insertBefore(mn.instructions.getFirst(), il);
}
/**
* Different unit test framework may have different @Test annotation
* but they should always NOT private, protected or static
* and has neither parameter nor return value
*/
private boolean couldBeTestMethod(MethodNode mn) {
return (mn.access & (ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC)) == 0 ;
return (mn.access & (ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC)) == 0 &&
mn.desc.equals(SIGNATURE_VOID_METHOD_WITHOUT_PARAMETER);
}
}

View File

@ -35,10 +35,10 @@ public class InvokeRecordUtil {
List<Object[]> records = getInvokeRecord(identify);
if (isConstructor) {
records.add(args);
LogUtil.verbose("Mock constructor invoked \"%s\"", identify);
LogUtil.verbose(" Mock constructor invoked \"%s\"", identify);
} else {
records.add(slice(args, 1));
LogUtil.verbose("Mock method invoked \"%s\"", identify);
LogUtil.verbose(" Mock method invoked \"%s\"", identify);
}
INVOKE_RECORDS.put(identify, records);
}

View File

@ -15,6 +15,10 @@ public class TestableUtil {
* [0]Thread.getStackTrace() [1]previousStackLocation() [2]Invoker -> [3]Caller of invoker
*/
private static final int INDEX_OF_CALLER_METHOD = 3;
/**
* [0]Thread.getStackTrace() [1]markTestCaseBegin() [2]TestCaseMethod
*/
private static final int INDEX_OF_TEST_CASE_METHOD = 2;
/**
* Just a special number to identify test worker thread
*/
@ -22,10 +26,9 @@ public class TestableUtil {
/**
* Get the last visit method in source file
* @param testClassRef usually `this` variable of the test class
* @return method name
*/
public static String currentSourceMethodName(Object testClassRef) {
public static String currentSourceMethodName() {
return Thread.currentThread().getStackTrace()[INDEX_OF_SOURCE_METHOD].getMethodName();
}
@ -79,6 +82,14 @@ public class TestableUtil {
return stack.getFileName() + ":" + stack.getLineNumber();
}
/**
* Do prepare when probable test case start
*/
public static void markTestCaseBegin() {
String testCaseName = Thread.currentThread().getStackTrace()[INDEX_OF_TEST_CASE_METHOD].getMethodName();
LogUtil.verbose("Start testcase: " + testCaseName);
}
private static Thread findTestWorkerThread(Set<Thread> threads) {
for (Thread t : threads) {
if (t.getPriority() == TEST_WORKER_THREAD_PRIORITY) {