fix: only generate named lambda method for mocked ones

This commit is contained in:
金戟
2022-05-28 13:26:37 +08:00
parent 006e742c28
commit 0a5666c0be
5 changed files with 35 additions and 23 deletions

View File

@@ -1,12 +1,5 @@
package com.alibaba.demo.lambda;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* @author jim
*/

View File

@@ -1,8 +1,6 @@
package com.alibaba.demo.lambda;
import com.alibaba.testable.core.annotation.MockDiagnose;
import com.alibaba.testable.core.annotation.MockInvoke;
import com.alibaba.testable.core.model.LogLevel;
import org.junit.jupiter.api.Test;
@@ -13,7 +11,6 @@ public class CollectionListCodeDemoTest {
private final CollectionListCodeDemo instance = new CollectionListCodeDemo();
//@MockDiagnose(LogLevel.VERBOSE)
public static class Mock {
@MockInvoke(targetClass = String.class, targetMethod = "contains")
public boolean mockContains(CharSequence s) {

View File

@@ -1,8 +1,6 @@
package com.alibaba.demo.lambda;
import com.alibaba.testable.core.annotation.MockDiagnose;
import com.alibaba.testable.core.annotation.MockInvoke;
import com.alibaba.testable.core.model.LogLevel;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
@@ -20,7 +18,6 @@ public class InvokeInterfaceDemoTest {
private final InvokeInterfaceDemo instance = new InvokeInterfaceDemo();
//@MockDiagnose(LogLevel.VERBOSE)
public static class Mock {
@MockInvoke(targetClass = InvokeInterfaceDemo.ILambda.class, targetMethod = "run")

View File

@@ -1,8 +1,6 @@
package com.alibaba.demo.lambda;
import com.alibaba.testable.core.annotation.MockDiagnose;
import com.alibaba.testable.core.annotation.MockInvoke;
import com.alibaba.testable.core.model.LogLevel;
import org.junit.jupiter.api.Test;
import static com.alibaba.testable.core.matcher.InvocationVerifier.verifyInvoked;
@@ -15,16 +13,21 @@ public class StaticInstanceReferenceTest {
private final StaticInstanceReference instance = new StaticInstanceReference();
//@MockDiagnose(LogLevel.VERBOSE)
public static class Mock {
@MockInvoke(targetClass = StaticInstanceReference.StaticClassA.class, targetMethod = "doIt")
private void mockDoIt() {
}
@MockInvoke(targetClass = StaticInstanceReference.StaticClassA.class)
private Integer function2(String s) {
return 2;
}
}
@Test
public void shouldMockDoIt() {
instance.staticMethodReference();
verifyInvoked("mockDoIt").withTimes(1);
verifyInvoked("function2").withTimes(1);
}
}

View File

@@ -11,10 +11,7 @@ import com.alibaba.testable.core.util.LogUtil;
import org.objectweb.asm.*;
import org.objectweb.asm.tree.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import static com.alibaba.testable.core.constant.ConstPool.CONSTRUCTOR;
@@ -47,6 +44,10 @@ public class SourceClassHandler extends BaseClassHandler {
@Override
protected void transform(ClassNode cn) {
LogUtil.diagnose("Found source class %s", cn.name);
if (injectMethods.isEmpty()) {
return;
}
Set<MethodInfo> memberInjectMethods = new HashSet<MethodInfo>();
Set<MethodInfo> newOperatorInjectMethods = new HashSet<MethodInfo>();
for (MethodInfo im : injectMethods) {
@@ -57,7 +58,9 @@ public class SourceClassHandler extends BaseClassHandler {
}
}
resolveMethodReference(cn);
if (!memberInjectMethods.isEmpty()) {
resolveMethodReference(cn, memberInjectMethods);
}
for (MethodNode m : cn.methods) {
transformMethod(m, memberInjectMethods, newOperatorInjectMethods);
@@ -355,11 +358,17 @@ public class SourceClassHandler extends BaseClassHandler {
return handleList;
}
private void resolveMethodReference(ClassNode cn) {
private void resolveMethodReference(ClassNode cn, Set<MethodInfo> mockedMethods) {
List<BsmArg> invokeDynamicList = new ArrayList<BsmArg>();
for (MethodNode method : cn.methods) {
List<BsmArg> handleList = fetchInvokeDynamicHandle(method);
invokeDynamicList.addAll(handleList);
for (BsmArg arg : handleList) {
for (MethodInfo mi : mockedMethods) {
if (isMethodMocked(arg.getHandle(), mi)) {
invokeDynamicList.add(arg);
}
}
}
}
// process for method reference
@@ -424,6 +433,19 @@ public class SourceClassHandler extends BaseClassHandler {
}
}
private boolean isMethodMocked(Handle targetHandle, MethodInfo mockMethodInfo) {
if (targetHandle.getTag() == Opcodes.H_INVOKEINTERFACE || targetHandle.getTag() == Opcodes.H_INVOKEVIRTUAL) {
String targetMockDesc = MethodUtil.addParameterAtBegin(mockMethodInfo.getDesc(),
ClassUtil.toByteCodeClassName(mockMethodInfo.getClazz()));
return mockMethodInfo.getClazz().equals(targetHandle.getOwner()) &&
mockMethodInfo.getName().equals(targetHandle.getName()) &&
targetMockDesc.equals(targetHandle.getDesc());
}
return mockMethodInfo.getClazz().equals(targetHandle.getOwner()) &&
mockMethodInfo.getName().equals(targetHandle.getName()) &&
mockMethodInfo.getDesc().equals(targetHandle.getDesc());
}
private void visitLocalVariableByArguments(MethodVisitor mv, final int initVar, Type[] argumentTypes, Label l0, Label l1) {
int nextLocalVar = initVar;
for (int i = 0; i < argumentTypes.length; i++) {