You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by li...@apache.org on 2019/12/20 16:59:52 UTC
[dubbo] branch 2.6.x updated: Dubbo 2.6.x cannot found correct
method with telnet command (#4611)
This is an automated email from the ASF dual-hosted git repository.
liujun pushed a commit to branch 2.6.x
in repository https://gitbox.apache.org/repos/asf/dubbo.git
The following commit(s) were added to refs/heads/2.6.x by this push:
new 69cc9bd Dubbo 2.6.x cannot found correct method with telnet command (#4611)
69cc9bd is described below
commit 69cc9bded69f8d0cc5f75dfa27478fa3636fcfc5
Author: 祁晓波 <qi...@gmail.com>
AuthorDate: Sat Dec 21 00:59:35 2019 +0800
Dubbo 2.6.x cannot found correct method with telnet command (#4611)
Fixes #4565
---
.../protocol/dubbo/telnet/InvokeTelnetHandler.java | 202 +++++++++++++-------
.../protocol/dubbo/telnet/SelectTelnetHandler.java | 59 ++++++
...com.alibaba.dubbo.remoting.telnet.TelnetHandler | 3 +-
.../rpc/protocol/dubbo/support/DemoService.java | 6 +
.../protocol/dubbo/support/DemoServiceImpl.java | 15 ++
.../dubbo/support/{DemoService.java => Man.java} | 53 ++----
.../dubbo/telnet/InvokerTelnetHandlerTest.java | 208 ++++++++++++++++-----
.../dubbo/telnet/SelectTelnetHandlerTest.java | 102 ++++++++++
8 files changed, 499 insertions(+), 149 deletions(-)
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/telnet/InvokeTelnetHandler.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/telnet/InvokeTelnetHandler.java
index 59733dc..43eac8d 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/telnet/InvokeTelnetHandler.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/telnet/InvokeTelnetHandler.java
@@ -17,6 +17,7 @@
package com.alibaba.dubbo.rpc.protocol.dubbo.telnet;
import com.alibaba.dubbo.common.extension.Activate;
+import com.alibaba.dubbo.common.utils.CollectionUtils;
import com.alibaba.dubbo.common.utils.PojoUtils;
import com.alibaba.dubbo.common.utils.ReflectUtils;
import com.alibaba.dubbo.common.utils.StringUtils;
@@ -31,6 +32,7 @@ import com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol;
import com.alibaba.fastjson.JSON;
import java.lang.reflect.Method;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@@ -41,66 +43,12 @@ import java.util.Map;
@Activate
@Help(parameter = "[service.]method(args)", summary = "Invoke the service method.", detail = "Invoke the service method.")
public class InvokeTelnetHandler implements TelnetHandler {
+ static final String INVOKE_MESSAGE_KEY = "telnet.invoke.method.message";
- private static Method findMethod(Exporter<?> exporter, String method, List<Object> args) {
- Invoker<?> invoker = exporter.getInvoker();
- Method[] methods = invoker.getInterface().getMethods();
- for (Method m : methods) {
- if (m.getName().equals(method) && isMatch(m.getParameterTypes(), args)) {
- return m;
- }
- }
- return null;
- }
-
- private static boolean isMatch(Class<?>[] types, List<Object> args) {
- if (types.length != args.size()) {
- return false;
- }
- for (int i = 0; i < types.length; i++) {
- Class<?> type = types[i];
- Object arg = args.get(i);
-
- if (arg == null) {
- // if the type is primitive, the method to invoke will cause NullPointerException definitely
- // so we can offer a specified error message to the invoker in advance and avoid unnecessary invoking
- if (type.isPrimitive()) {
- throw new NullPointerException(String.format(
- "The type of No.%d parameter is primitive(%s), but the value passed is null.", i + 1, type.getName()));
- }
+ static final String INVOKE_METHOD_LIST_KEY = "telnet.invoke.method.list";
- // if the type is not primitive, we choose to believe what the invoker want is a null value
- continue;
- }
-
- if (ReflectUtils.isPrimitive(arg.getClass())) {
- if (!ReflectUtils.isPrimitive(type)) {
- return false;
- }
- } else if (arg instanceof Map) {
- String name = (String) ((Map<?, ?>) arg).get("class");
- Class<?> cls = arg.getClass();
- if (name != null && name.length() > 0) {
- cls = ReflectUtils.forName(name);
- }
- if (!type.isAssignableFrom(cls)) {
- return false;
- }
- } else if (arg instanceof Collection) {
- if (!type.isArray() && !type.isAssignableFrom(arg.getClass())) {
- return false;
- }
- } else {
- if (!type.isAssignableFrom(arg.getClass())) {
- return false;
- }
- }
- }
- return true;
- }
@Override
- @SuppressWarnings("unchecked")
public String telnet(Channel channel, String message) {
if (message == null || message.length() == 0) {
return "Please input method name, eg: \r\ninvoke xxxMethod(1234, \"abcd\", {\"prop\" : \"value\"})\r\ninvoke XxxService.xxxMethod(1234, \"abcd\", {\"prop\" : \"value\"})\r\ninvoke com.xxx.XxxService.xxxMethod(1234, \"abcd\", {\"prop\" : \"value\"})";
@@ -129,23 +77,51 @@ public class InvokeTelnetHandler implements TelnetHandler {
}
Invoker<?> invoker = null;
Method invokeMethod = null;
- for (Exporter<?> exporter : DubboProtocol.getDubboProtocol().getExporters()) {
- if (service == null || service.length() == 0) {
- invokeMethod = findMethod(exporter, method, list);
- if (invokeMethod != null) {
+ Collection<Exporter<?>> exporters = DubboProtocol.getDubboProtocol().getExporters();
+ if (isInvokedSelectCommand(channel)) {
+ invokeMethod = (Method) channel.getAttribute(SelectTelnetHandler.SELECT_METHOD_KEY);
+ for (Exporter<?> exporter : exporters) {
+ if (invokeMethod.getDeclaringClass().getName().equals(exporter.getInvoker().getInterface().getName())) {
invoker = exporter.getInvoker();
break;
}
- } else {
- if (service.equals(exporter.getInvoker().getInterface().getSimpleName())
+ }
+ } else {
+ if ((StringUtils.isBlank(service))) {
+ if (exporters.size() != 1) {
+ //no default service we should not continue
+ return "Failed to find service !";
+ }
+ }
+ for (Exporter<?> exporter : exporters) {
+ if (StringUtils.isBlank(service)
+ || service.equals(exporter.getInvoker().getInterface().getSimpleName())
|| service.equals(exporter.getInvoker().getInterface().getName())
|| service.equals(exporter.getInvoker().getUrl().getPath())) {
- invokeMethod = findMethod(exporter, method, list);
invoker = exporter.getInvoker();
+ List<Method> methodList = findSameSignatureMethod(exporter.getInvoker().getInterface(), method, list);
+ if (CollectionUtils.isNotEmpty(methodList)) {
+ if (methodList.size() == 1) {
+ invokeMethod = methodList.get(0);
+ } else {
+ List<Method> matchMethods = findMatchMethods(methodList, list);
+ if (CollectionUtils.isNotEmpty(matchMethods)) {
+ if (matchMethods.size() == 1) {
+ invokeMethod = matchMethods.get(0);
+ } else { //exist overridden method
+ channel.setAttribute(INVOKE_METHOD_LIST_KEY, matchMethods);
+ channel.setAttribute(INVOKE_MESSAGE_KEY, message);
+ printSelectMessage(buf, matchMethods);
+ return buf.toString();
+ }
+ }
+ }
+ }
break;
}
}
}
+
if (invoker != null) {
if (invokeMethod != null) {
try {
@@ -170,4 +146,104 @@ public class InvokeTelnetHandler implements TelnetHandler {
return buf.toString();
}
+ private List<Method> findSameSignatureMethod(Class clazz, String lookupMethodName, List<Object> args) {
+ List<Method> sameSignatureMethods = new ArrayList<Method>();
+ Method[] declaredMethods = clazz.getDeclaredMethods();
+ for (Method method : declaredMethods) {
+ if (method.getName().equals(lookupMethodName) && method.getParameterTypes().length == args.size()) {
+ sameSignatureMethods.add(method);
+ }
+ }
+ return sameSignatureMethods;
+ }
+
+ private List<Method> findMatchMethods(List<Method> methods, List<Object> args) {
+ List<Method> matchMethod = new ArrayList<Method>();
+ for (Method method : methods) {
+ if (isMatch(method, args)) {
+ matchMethod.add(method);
+ }
+ }
+ return matchMethod;
+ }
+
+ private static boolean isMatch(Method method, List<Object> args) {
+ Class<?>[] types = method.getParameterTypes();
+ if (types.length != args.size()) {
+ return false;
+ }
+ for (int i = 0; i < types.length; i++) {
+ Class<?> type = types[i];
+ Object arg = args.get(i);
+
+ if (arg == null) {
+ if (type.isPrimitive()) {
+ return false;
+ }
+
+ // if the type is not primitive, we choose to believe what the invoker want is a null value
+ continue;
+ }
+
+ if (ReflectUtils.isPrimitive(arg.getClass())) {
+ // allow string arg to enum type, @see PojoUtils.realize0()
+ if (arg instanceof String && type.isEnum()) {
+ continue;
+ }
+
+ if (!ReflectUtils.isPrimitive(type)) {
+ return false;
+ }
+
+ if (!ReflectUtils.isCompatible(type, arg)) {
+ return false;
+ }
+ } else if (arg instanceof Map) {
+ String name = (String) ((Map<?, ?>) arg).get("class");
+ if (StringUtils.isNotEmpty(name)) {
+ Class<?> cls = ReflectUtils.forName(name);
+ if (!type.isAssignableFrom(cls)) {
+ return false;
+ }
+ } else {
+ return true;
+ }
+ } else if (arg instanceof Collection) {
+ if (!type.isArray() && !type.isAssignableFrom(arg.getClass())) {
+ return false;
+ }
+ } else {
+ if (!type.isAssignableFrom(arg.getClass())) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+
+ private void printSelectMessage(StringBuilder buf, List<Method> methods) {
+ buf.append("Methods:\r\n");
+ for (int i = 0; i < methods.size(); i++) {
+ Method method = methods.get(i);
+ buf.append(i + 1).append(". ").append(method.getName()).append("(");
+ Class<?>[] parameterTypes = method.getParameterTypes();
+ for (int n = 0; n < parameterTypes.length; n++) {
+ buf.append(parameterTypes[n].getSimpleName());
+ if (n != parameterTypes.length - 1) {
+ buf.append(",");
+ }
+ }
+ buf.append(")\r\n");
+ }
+ buf.append("Please use the select command to select the method you want to invoke. eg: select 1");
+ }
+
+ private boolean isInvokedSelectCommand(Channel channel) {
+ if (channel.hasAttribute(SelectTelnetHandler.SELECT_KEY)) {
+ channel.removeAttribute(SelectTelnetHandler.SELECT_KEY);
+ return true;
+ }
+ return false;
+ }
}
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/telnet/SelectTelnetHandler.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/telnet/SelectTelnetHandler.java
new file mode 100644
index 0000000..7d26c2a
--- /dev/null
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/telnet/SelectTelnetHandler.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.dubbo.rpc.protocol.dubbo.telnet;
+
+import com.alibaba.dubbo.common.extension.Activate;
+import com.alibaba.dubbo.common.utils.CollectionUtils;
+import com.alibaba.dubbo.common.utils.StringUtils;
+import com.alibaba.dubbo.remoting.Channel;
+import com.alibaba.dubbo.remoting.telnet.TelnetHandler;
+import com.alibaba.dubbo.remoting.telnet.support.Help;
+
+import java.lang.reflect.Method;
+import java.util.List;
+/**
+ * SelectTelnetHandler
+ */
+@Activate
+@Help(parameter = "[index]", summary = "Select the index of the method you want to invoke.",
+ detail = "Select the index of the method you want to invoke.")
+public class SelectTelnetHandler implements TelnetHandler {
+ static final String SELECT_METHOD_KEY = "telnet.select.method";
+ static final String SELECT_KEY = "telnet.select";
+
+ private InvokeTelnetHandler invokeTelnetHandler = new InvokeTelnetHandler();
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public String telnet(Channel channel, String message) {
+ if (message == null || message.length() == 0) {
+ return "Please input the index of the method you want to invoke, eg: \r\n select 1";
+ }
+ List<Method> methodList = (List<Method>) channel.getAttribute(InvokeTelnetHandler.INVOKE_METHOD_LIST_KEY);
+ if (CollectionUtils.isEmpty(methodList)) {
+ return "Please use the invoke command first.";
+ }
+ if (!StringUtils.isInteger(message) || Integer.parseInt(message) < 1 || Integer.parseInt(message) > methodList.size()) {
+ return "Illegal index ,please input select 1~" + methodList.size();
+ }
+ Method method = methodList.get(Integer.parseInt(message));
+ channel.setAttribute(SELECT_METHOD_KEY, method);
+ channel.setAttribute(SELECT_KEY, Boolean.TRUE);
+ String invokeMessage = (String) channel.getAttribute(InvokeTelnetHandler.INVOKE_MESSAGE_KEY);
+ return invokeTelnetHandler.telnet(channel, invokeMessage);
+ }
+}
\ No newline at end of file
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.remoting.telnet.TelnetHandler b/dubbo-rpc/dubbo-rpc-dubbo/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.remoting.telnet.TelnetHandler
index 33ebee2..eb6f8cd 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.remoting.telnet.TelnetHandler
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.remoting.telnet.TelnetHandler
@@ -4,4 +4,5 @@ cd=com.alibaba.dubbo.rpc.protocol.dubbo.telnet.ChangeTelnetHandler
pwd=com.alibaba.dubbo.rpc.protocol.dubbo.telnet.CurrentTelnetHandler
invoke=com.alibaba.dubbo.rpc.protocol.dubbo.telnet.InvokeTelnetHandler
trace=com.alibaba.dubbo.rpc.protocol.dubbo.telnet.TraceTelnetHandler
-count=com.alibaba.dubbo.rpc.protocol.dubbo.telnet.CountTelnetHandler
\ No newline at end of file
+count=com.alibaba.dubbo.rpc.protocol.dubbo.telnet.CountTelnetHandler
+select=com.alibaba.dubbo.rpc.protocol.dubbo.telnet.SelectTelnetHandler
\ No newline at end of file
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/support/DemoService.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/support/DemoService.java
index 93c48f5..e86ff60 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/support/DemoService.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/support/DemoService.java
@@ -59,4 +59,10 @@ public interface DemoService {
long add(int a, long b);
+ int getPerson(Person person);
+
+ int getPerson(Person person1, Person perso2);
+
+ String getPerson(Man man);
+
}
\ No newline at end of file
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/support/DemoServiceImpl.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/support/DemoServiceImpl.java
index 50d98e6..6eb42a6 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/support/DemoServiceImpl.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/support/DemoServiceImpl.java
@@ -108,4 +108,19 @@ public class DemoServiceImpl implements DemoService {
return a + b;
}
+ @Override
+ public int getPerson(Person person) {
+ return person.getAge();
+ }
+
+ @Override
+ public int getPerson(Person person1, Person perso2) {
+ return person1.getAge() + perso2.getAge();
+ }
+
+ @Override
+ public String getPerson(Man man) {
+ return man.getName();
+ }
+
}
\ No newline at end of file
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/support/DemoService.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/support/Man.java
similarity index 54%
copy from dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/support/DemoService.java
copy to dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/support/Man.java
index 93c48f5..ecd063e 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/support/DemoService.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/support/Man.java
@@ -16,47 +16,30 @@
*/
package com.alibaba.dubbo.rpc.protocol.dubbo.support;
-import java.util.Map;
-import java.util.Set;
-
+import java.io.Serializable;
/**
- * <code>TestService</code>
+ * Man.java
*/
+public class Man implements Serializable {
-public interface DemoService {
- void sayHello(String name);
-
- Set<String> keys(Map<String, String> map);
-
- String echo(String text);
-
- Map echo(Map map);
-
- long timestamp();
-
- String getThreadName();
-
- int getSize(String[] strs);
-
- int getSize(Object[] os);
-
- Object invoke(String service, String method) throws Exception;
-
- int stringLength(String str);
-
- Type enumlength(Type... types);
-
-// Type enumlength(Type type);
-
- String get(CustomArgument arg1);
-
- byte getbyte(byte arg);
+ private static final long serialVersionUID = 1L;
+ private String name;
+ private int age;
- void nonSerializedParameter(NonSerialized ns);
+ public String getName() {
+ return name;
+ }
- NonSerialized returnNonSerialized();
+ public void setName(String name) {
+ this.name = name;
+ }
- long add(int a, long b);
+ public int getAge() {
+ return age;
+ }
+ public void setAge(int age) {
+ this.age = age;
+ }
}
\ No newline at end of file
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/telnet/InvokerTelnetHandlerTest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/telnet/InvokerTelnetHandlerTest.java
index eb4368d..6fff3de 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/telnet/InvokerTelnetHandlerTest.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/telnet/InvokerTelnetHandlerTest.java
@@ -16,27 +16,32 @@
*/
package com.alibaba.dubbo.rpc.protocol.dubbo.telnet;
+import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.URL;
+import com.alibaba.dubbo.common.extension.ExtensionLoader;
import com.alibaba.dubbo.common.utils.NetUtils;
import com.alibaba.dubbo.remoting.Channel;
+import com.alibaba.dubbo.remoting.ChannelHandler;
import com.alibaba.dubbo.remoting.RemotingException;
import com.alibaba.dubbo.remoting.telnet.TelnetHandler;
-import com.alibaba.dubbo.rpc.Invocation;
-import com.alibaba.dubbo.rpc.Invoker;
-import com.alibaba.dubbo.rpc.RpcResult;
-import com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol;
+import com.alibaba.dubbo.rpc.*;
import com.alibaba.dubbo.rpc.protocol.dubbo.support.DemoService;
+import com.alibaba.dubbo.rpc.protocol.dubbo.support.DemoServiceImpl;
import com.alibaba.dubbo.rpc.protocol.dubbo.support.ProtocolUtils;
import org.junit.After;
+import org.junit.Before;
import org.junit.Test;
+import java.net.InetSocketAddress;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
/**
* CountTelnetHandlerTest.java
@@ -44,81 +49,98 @@ import static org.mockito.Mockito.mock;
public class InvokerTelnetHandlerTest {
private static TelnetHandler invoke = new InvokeTelnetHandler();
+ private static TelnetHandler select = new SelectTelnetHandler();
+ private Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
+ private ProxyFactory proxy = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
+
+
private Channel mockChannel;
- private Invoker<DemoService> mockInvoker;
@After
public void after() {
ProtocolUtils.closeAll();
}
- @SuppressWarnings("unchecked")
+ @Before
+ public void setUp() {
+ DemoService service = new DemoServiceImpl();
+ protocol.export(proxy.getInvoker(service, DemoService.class, URL.valueOf("dubbo://127.0.0.1:20886/demo").addParameter(Constants.INTERFACE_KEY, DemoService.class.getName())));
+
+ }
+
@Test
public void testInvokeDefaultSService() throws RemotingException {
- mockInvoker = mock(Invoker.class);
- given(mockInvoker.getInterface()).willReturn(DemoService.class);
- given(mockInvoker.getUrl()).willReturn(URL.valueOf("dubbo://127.0.0.1:20886/demo"));
- given(mockInvoker.invoke(any(Invocation.class))).willReturn(new RpcResult("ok"));
mockChannel = mock(Channel.class);
given(mockChannel.getAttribute("telnet.service")).willReturn("com.alibaba.dubbo.rpc.protocol.dubbo.support.DemoService");
given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
-
- DubboProtocol.getDubboProtocol().export(mockInvoker);
String result = invoke.telnet(mockChannel, "DemoService.echo(\"ok\")");
assertTrue(result.contains("Use default service com.alibaba.dubbo.rpc.protocol.dubbo.support.DemoService.\r\n\"ok\"\r\n"));
}
- @SuppressWarnings("unchecked")
@Test
- public void testInvokeByPassingNullValue() throws RemotingException {
- mockInvoker = mock(Invoker.class);
- given(mockInvoker.getInterface()).willReturn(DemoService.class);
- given(mockInvoker.getUrl()).willReturn(URL.valueOf("dubbo://127.0.0.1:20886/demo"));
- given(mockInvoker.invoke(any(Invocation.class))).willReturn(new RpcResult("ok"));
+ public void testInvokeDefaultService() throws RemotingException {
mockChannel = mock(Channel.class);
- given(mockChannel.getAttribute("telnet.service")).willReturn("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService");
+ given(mockChannel.getAttribute("telnet.service")).willReturn(DemoService.class.getName());
+ given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
+ given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
+ String result = invoke.telnet(mockChannel, "echo(\"ok\")");
+ assertTrue(result.contains("\"ok\""));
+ }
+
+
+ @Test
+ public void testInvokeByPassingNullValue() {
+ mockChannel = mock(Channel.class);
+ given(mockChannel.getAttribute("telnet.service")).willReturn(DemoService.class.getName());
given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
- DubboProtocol.getDubboProtocol().export(mockInvoker);
- // pass null value to parameter of primitive type
- try {
- invoke.telnet(mockChannel, "DemoService.add(null, 2)");
- fail("It should cause a NullPointerException by the above code.");
- } catch (NullPointerException ex) {
- String message = ex.getMessage();
- assertEquals("The type of No.1 parameter is primitive(int), but the value passed is null.", message);
- }
- try {
- invoke.telnet(mockChannel, "DemoService.add(1, null)");
- fail("It should cause a NullPointerException by the above code.");
- } catch (NullPointerException ex) {
- String message = ex.getMessage();
- assertEquals("The type of No.2 parameter is primitive(long), but the value passed is null.", message);
- }
- // pass null value to parameter of object type
try {
- invoke.telnet(mockChannel, "DemoService.sayHello(null)");
- } catch (NullPointerException ex) {
- fail("It shouldn't cause a NullPointerException by the above code.");
+ invoke.telnet(mockChannel, "sayHello(null)");
+ } catch (Exception ex) {
+ assertTrue(ex instanceof NullPointerException);
}
}
- @SuppressWarnings("unchecked")
+
+ @Test
+ public void testOverriddenMethodWithSpecifyParamType() throws RemotingException {
+ mockChannel = mock(Channel.class);
+ given(mockChannel.getAttribute("telnet.service")).willReturn(DemoService.class.getName());
+ given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
+ given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
+
+ String result = invoke.telnet(mockChannel, "getPerson({\"name\":\"zhangsan\",\"age\":12,\"class\":\"com.alibaba.dubbo.rpc.protocol.dubbo.support.Person\"})");
+ assertTrue(result.contains("12"));
+ }
+
+ @Test
+ public void testInvokeOverriddenMethodBySelect() throws RemotingException {
+ //create a real instance to keep the attribute values;
+ mockChannel = spy(getChannelInstance());
+ given(mockChannel.getAttribute("telnet.service")).willReturn(DemoService.class.getName());
+ given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
+ given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
+
+ String param = "{\"name\":\"Dubbo\",\"age\":8}";
+ String result = invoke.telnet(mockChannel, "getPerson(" + param + ")");
+ assertTrue(result.contains("Please use the select command to select the method you want to invoke. eg: select 1"));
+ result = select.telnet(mockChannel, "1");
+ //result dependent on method order.
+ assertTrue(result.contains("8") || result.contains("\"Dubbo\""));
+ }
+
@Test
- public void testInvokeAutoFindMethod() throws RemotingException {
- mockInvoker = mock(Invoker.class);
- given(mockInvoker.getInterface()).willReturn(DemoService.class);
- given(mockInvoker.getUrl()).willReturn(URL.valueOf("dubbo://127.0.0.1:20886/demo"));
- given(mockInvoker.invoke(any(Invocation.class))).willReturn(new RpcResult("ok"));
+ public void testInvokeMultiJsonParamMethod() throws RemotingException {
mockChannel = mock(Channel.class);
given(mockChannel.getAttribute("telnet.service")).willReturn(null);
given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
- DubboProtocol.getDubboProtocol().export(mockInvoker);
- String result = invoke.telnet(mockChannel, "echo(\"ok\")");
- assertTrue(result.contains("ok"));
+
+ String param = "{\"name\":\"Dubbo\",\"age\":8},{\"name\":\"Apache\",\"age\":20}";
+ String result = invoke.telnet(mockChannel, "getPerson(" + param + ")");
+ assertTrue(result.contains("28"));
}
@Test
@@ -139,4 +161,90 @@ public class InvokerTelnetHandlerTest {
String result = invoke.telnet(mockChannel, "(");
assertEquals("Invalid parameters, format: service.method(args)", result);
}
+
+ private Channel getChannelInstance() {
+ return new Channel() {
+ private final Map<String, Object> attributes = new ConcurrentHashMap<String, Object>();
+
+ @Override
+ public InetSocketAddress getRemoteAddress() {
+ return null;
+ }
+
+ @Override
+ public boolean isConnected() {
+ return false;
+ }
+
+ @Override
+ public boolean hasAttribute(String key) {
+ return attributes.containsKey(key);
+ }
+
+ @Override
+ public Object getAttribute(String key) {
+ return attributes.get(key);
+ }
+
+ @Override
+ public void setAttribute(String key, Object value) {
+ if (value == null) { // The null value unallowed in the ConcurrentHashMap.
+ attributes.remove(key);
+ } else {
+ attributes.put(key, value);
+ }
+ }
+
+ @Override
+ public void removeAttribute(String key) {
+ attributes.remove(key);
+ }
+
+
+ @Override
+ public URL getUrl() {
+ return null;
+ }
+
+ @Override
+ public ChannelHandler getChannelHandler() {
+ return null;
+ }
+
+ @Override
+ public InetSocketAddress getLocalAddress() {
+ return null;
+ }
+
+ @Override
+ public void send(Object message) {
+
+ }
+
+ @Override
+ public void send(Object message, boolean sent) {
+
+ }
+
+ @Override
+ public void close() {
+
+ }
+
+ @Override
+ public void close(int timeout) {
+
+ }
+
+ @Override
+ public void startClose() {
+
+ }
+
+ @Override
+ public boolean isClosed() {
+ return false;
+ }
+ };
+ }
}
\ No newline at end of file
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/telnet/SelectTelnetHandlerTest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/telnet/SelectTelnetHandlerTest.java
new file mode 100644
index 0000000..ba3c1bd
--- /dev/null
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/telnet/SelectTelnetHandlerTest.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.dubbo.rpc.protocol.dubbo.telnet;
+
+import com.alibaba.dubbo.common.utils.NetUtils;
+import com.alibaba.dubbo.remoting.Channel;
+import com.alibaba.dubbo.remoting.RemotingException;
+import com.alibaba.dubbo.remoting.telnet.TelnetHandler;
+import com.alibaba.dubbo.rpc.protocol.dubbo.support.DemoService;
+import com.alibaba.dubbo.rpc.protocol.dubbo.support.ProtocolUtils;
+import org.junit.*;
+
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Mockito.mock;
+
+public class SelectTelnetHandlerTest {
+ private static TelnetHandler select = new SelectTelnetHandler();
+ private Channel mockChannel;
+ List<Method> methods;
+
+ @Before
+ public void setup() {
+ String methodName = "getPerson";
+ methods = new ArrayList<Method>();
+ for (Method method : DemoService.class.getMethods()) {
+ if (method.getName().equals(methodName)) {
+ methods.add(method);
+ }
+ }
+
+ }
+
+ @After
+ public void after() {
+ ProtocolUtils.closeAll();
+ }
+
+ @Test
+ public void testInvokeWithoutMethodList() throws RemotingException {
+ mockChannel = mock(Channel.class);
+ given(mockChannel.getAttribute("telnet.service")).willReturn(DemoService.class.getName());
+ given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
+ given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
+
+
+ String result = select.telnet(mockChannel, "1");
+ assertTrue(result.contains("Please use the invoke command first."));
+ }
+
+ @Test
+ public void testInvokeWithIllegalMessage() throws RemotingException {
+ mockChannel = mock(Channel.class);
+ given(mockChannel.getAttribute("telnet.service")).willReturn(DemoService.class.getName());
+ given(mockChannel.getAttribute(InvokeTelnetHandler.INVOKE_METHOD_LIST_KEY)).willReturn(methods);
+ given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
+ given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
+
+
+ String result = select.telnet(mockChannel, "index");
+ assertTrue(result.contains("Illegal index ,please input select 1"));
+
+ result = select.telnet(mockChannel, "0");
+ assertTrue(result.contains("Illegal index ,please input select 1"));
+
+ result = select.telnet(mockChannel, "1000");
+ assertTrue(result.contains("Illegal index ,please input select 1"));
+ }
+
+ @Test
+ public void testInvokeWithNull() throws RemotingException {
+ mockChannel = mock(Channel.class);
+ given(mockChannel.getAttribute("telnet.service")).willReturn(DemoService.class.getName());
+ given(mockChannel.getAttribute(InvokeTelnetHandler.INVOKE_METHOD_LIST_KEY)).willReturn(methods);
+ given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
+ given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
+
+
+ String result = select.telnet(mockChannel, null);
+ assertTrue(result.contains("Please input the index of the method you want to invoke"));
+ }
+}
+