blob: f65de858cba13b574a4ab0382504daf10e846e73 [file] [log] [blame]
/*
* Copyright 1999-2011 Alibaba Group.
*
* Licensed 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.cluster.support;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import org.easymock.EasyMock;
import org.junit.Before;
import org.junit.Test;
import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcException;
import com.alibaba.dubbo.rpc.RpcInvocation;
import com.alibaba.dubbo.rpc.RpcResult;
import com.alibaba.dubbo.rpc.cluster.Directory;
import com.alibaba.dubbo.rpc.cluster.directory.StaticDirectory;
import com.alibaba.dubbo.rpc.protocol.AbstractInvoker;
/**
* FailoverClusterInvokerTest
* @author liuchao
*
*/
@SuppressWarnings("unchecked")
public class FailoverClusterInvokerTest {
List<Invoker<FailoverClusterInvokerTest>> invokers = new ArrayList<Invoker<FailoverClusterInvokerTest>>();
int retries = 5;
URL url = URL.valueOf("test://test:11/test?retries="+retries);
Invoker<FailoverClusterInvokerTest> invoker1 = EasyMock.createMock(Invoker.class);
Invoker<FailoverClusterInvokerTest> invoker2 = EasyMock.createMock(Invoker.class);
RpcInvocation invocation = new RpcInvocation();
Directory<FailoverClusterInvokerTest> dic ;
Result result = new RpcResult();
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
dic = EasyMock.createMock(Directory.class);
EasyMock.expect(dic.getUrl()).andReturn(url).anyTimes();
EasyMock.expect(dic.list(invocation)).andReturn(invokers).anyTimes();
EasyMock.expect(dic.getInterface()).andReturn(FailoverClusterInvokerTest.class).anyTimes();
invocation.setMethodName("method1");
EasyMock.replay(dic);
invokers.add(invoker1);
invokers.add(invoker2);
}
@Test
public void testInvokeWithRuntimeException() {
EasyMock.reset(invoker1);
EasyMock.expect(invoker1.invoke(invocation)).andThrow(new RuntimeException()).anyTimes();
EasyMock.expect(invoker1.isAvailable()).andReturn(true).anyTimes();
EasyMock.expect(invoker1.getUrl()).andReturn(url).anyTimes();
EasyMock.expect(invoker1.getInterface()).andReturn(FailoverClusterInvokerTest.class).anyTimes();
EasyMock.replay(invoker1);
EasyMock.reset(invoker2);
EasyMock.expect(invoker2.invoke(invocation)).andThrow(new RuntimeException()).anyTimes();
EasyMock.expect(invoker2.isAvailable()).andReturn(true).anyTimes();
EasyMock.expect(invoker2.getUrl()).andReturn(url).anyTimes();
EasyMock.expect(invoker2.getInterface()).andReturn(FailoverClusterInvokerTest.class).anyTimes();
EasyMock.replay(invoker2);
FailoverClusterInvoker<FailoverClusterInvokerTest> invoker = new FailoverClusterInvoker<FailoverClusterInvokerTest>(dic);
try {
invoker.invoke(invocation);
fail();
} catch (RpcException expected) {
assertEquals(0,expected.getCode());
assertFalse(expected.getCause() instanceof RpcException);
}
}
@Test()
public void testInvokeWithRPCException() {
EasyMock.reset(invoker1);
EasyMock.expect(invoker1.invoke(invocation)).andThrow(new RpcException()).anyTimes();
EasyMock.expect(invoker1.isAvailable()).andReturn(true).anyTimes();
EasyMock.expect(invoker1.getUrl()).andReturn(url).anyTimes();
EasyMock.expect(invoker1.getInterface()).andReturn(FailoverClusterInvokerTest.class).anyTimes();
EasyMock.replay(invoker1);
EasyMock.reset(invoker2);
EasyMock.expect(invoker2.invoke(invocation)).andReturn(result).anyTimes();
EasyMock.expect(invoker2.isAvailable()).andReturn(true).anyTimes();
EasyMock.expect(invoker2.getUrl()).andReturn(url).anyTimes();
EasyMock.expect(invoker2.getInterface()).andReturn(FailoverClusterInvokerTest.class).anyTimes();
EasyMock.replay(invoker2);
FailoverClusterInvoker<FailoverClusterInvokerTest> invoker = new FailoverClusterInvoker<FailoverClusterInvokerTest>(dic);
for(int i=0;i<100;i++){
Result ret = invoker.invoke(invocation);
assertSame(result, ret);
}
}
@Test()
public void testInvoke_retryTimes() {
EasyMock.reset(invoker1);
EasyMock.expect(invoker1.invoke(invocation)).andThrow(new RpcException(RpcException.TIMEOUT_EXCEPTION)).anyTimes();
EasyMock.expect(invoker1.isAvailable()).andReturn(false).anyTimes();
EasyMock.expect(invoker1.getUrl()).andReturn(url).anyTimes();
EasyMock.expect(invoker1.getInterface()).andReturn(FailoverClusterInvokerTest.class).anyTimes();
EasyMock.replay(invoker1);
EasyMock.reset(invoker2);
EasyMock.expect(invoker2.invoke(invocation)).andThrow(new RpcException()).anyTimes();
EasyMock.expect(invoker2.isAvailable()).andReturn(false).anyTimes();
EasyMock.expect(invoker2.getUrl()).andReturn(url).anyTimes();
EasyMock.expect(invoker2.getInterface()).andReturn(FailoverClusterInvokerTest.class).anyTimes();
EasyMock.replay(invoker2);
FailoverClusterInvoker<FailoverClusterInvokerTest> invoker = new FailoverClusterInvoker<FailoverClusterInvokerTest>(dic);
try{
Result ret = invoker.invoke(invocation);
assertSame(result, ret);
fail();
}catch (RpcException expected) {
assertTrue(expected.isTimeout());
assertTrue(expected.getMessage().indexOf((retries+1)+" times")>0);
}
}
@Test()
public void testNoInvoke() {
dic = EasyMock.createMock(Directory.class);
EasyMock.expect(dic.getUrl()).andReturn(url).anyTimes();
EasyMock.expect(dic.list(invocation)).andReturn(null).anyTimes();
EasyMock.expect(dic.getInterface()).andReturn(FailoverClusterInvokerTest.class).anyTimes();
invocation.setMethodName("method1");
EasyMock.replay(dic);
invokers.add(invoker1);
FailoverClusterInvoker<FailoverClusterInvokerTest> invoker = new FailoverClusterInvoker<FailoverClusterInvokerTest>(dic);
try {
invoker.invoke(invocation);
fail();
} catch (RpcException expected) {
assertFalse(expected.getCause() instanceof RpcException);
}
}
/**
* 测试在调用重试过程中,directory列表变更,invoke重试时重新进行list选择
*/
@Test
public void testInvokerDestoryAndReList(){
final URL url = URL.valueOf("test://localhost/"+ Demo.class.getName() + "?loadbalance=roundrobin&retries="+retries);
RpcException exception = new RpcException(RpcException.TIMEOUT_EXCEPTION);
MockInvoker<Demo> invoker1 = new MockInvoker<Demo>(Demo.class, url);
invoker1.setException(exception);
MockInvoker<Demo> invoker2 = new MockInvoker<Demo>(Demo.class, url);
invoker2.setException(exception);
final List<Invoker<Demo>> invokers = new ArrayList<Invoker<Demo>>();
invokers.add(invoker1);
invokers.add(invoker2);
Callable<Object> callable = new Callable<Object>() {
public Object call() throws Exception {
//模拟invoker全部被destroy掉
for (Invoker<Demo> invoker:invokers){
invoker.destroy();
}
invokers.clear();
MockInvoker<Demo> invoker3 = new MockInvoker<Demo>(Demo.class, url);
invokers.add(invoker3);
return null;
}
};
invoker1.setCallable(callable);
invoker2.setCallable(callable);
RpcInvocation inv = new RpcInvocation();
inv.setMethodName("test");
Directory<Demo> dic = new MockDirectory<Demo>(url, invokers);
FailoverClusterInvoker<Demo> clusterinvoker = new FailoverClusterInvoker<Demo>(dic);
clusterinvoker.invoke(inv);
}
public static interface Demo{}
public static class MockInvoker<T> extends AbstractInvoker<T> {
URL url;
boolean available = true;
boolean destoryed = false;
Result result ;
RpcException exception;
Callable<?> callable;
public MockInvoker(Class<T> type, URL url) {
super(type, url);
}
public void setResult(Result result) {
this.result = result;
}
public void setException(RpcException exception) {
this.exception = exception;
}
public void setCallable(Callable<?> callable) {
this.callable = callable;
}
@Override
protected Result doInvoke(Invocation invocation) throws Throwable {
if (callable != null) {
try {
callable.call();
} catch (Exception e) {
throw new RpcException(e);
}
}
if (exception != null) {
throw exception;
} else {
return result;
}
}
}
public class MockDirectory<T> extends StaticDirectory<T> {
public MockDirectory(URL url , List<Invoker<T>> invokers) {
super(url, invokers);
}
@Override
protected List<Invoker<T>> doList(Invocation invocation) throws RpcException {
return new ArrayList<Invoker<T>>(super.doList(invocation));
}
}
}