blob: 4dee1b4a0ce7aa1a73a147db7c0fde091467d4c6 [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.protocol.dubbo;
import java.lang.reflect.Field;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
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.DubboAppender;
import com.alibaba.dubbo.common.utils.LogUtil;
import com.alibaba.dubbo.common.utils.NetUtils;
import com.alibaba.dubbo.remoting.exchange.ExchangeClient;
import com.alibaba.dubbo.rpc.Exporter;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.ProxyFactory;
public class ReferenceCountExchangeClientTest {
Exporter<?> demoExporter ;
Exporter<?> helloExporter ;
Invoker<IDemoService> demoServiceInvoker;
Invoker<IHelloService> helloServiceInvoker;
IDemoService demoService ;
IHelloService helloService;
ExchangeClient demoClient ;
ExchangeClient helloClient ;
String errorMsg = "safe guard client , should not be called ,must have a bug";
public interface IDemoService{
public String demo();
}
public class DemoServiceImpl implements IDemoService{
public String demo(){
return "demo";
}
}
public interface IHelloService{
public String hello();
}
public class HelloServiceImpl implements IHelloService{
public String hello(){
return "hello";
}
}
@BeforeClass
public static void setUpBeforeClass() throws Exception {
}
@Before
public void setUp() throws Exception {
}
/**
* 测试共享连接
*/
@Test
public void test_share_connect(){
init(0);
Assert.assertEquals(demoClient.getLocalAddress(), helloClient.getLocalAddress());
Assert.assertEquals(demoClient, helloClient);
destoy();
}
/**
* 测试不共享连接
*/
@Test
public void test_not_share_connect(){
init(1);
Assert.assertNotSame(demoClient.getLocalAddress(), helloClient.getLocalAddress());
Assert.assertNotSame(demoClient, helloClient);
destoy();
}
/**
* 测试invoker多次destory不会导致计数器多次减少
*/
@Test
public void test_multi_destory(){
init(0);
DubboAppender.doStart();
DubboAppender.clear();
demoServiceInvoker.destroy();
demoServiceInvoker.destroy();
Assert.assertEquals("hello", helloService.hello());
Assert.assertEquals("should not warning message", 0, LogUtil.findMessage(errorMsg));
LogUtil.checkNoError();
DubboAppender.doStop();
destoy();
}
/**
* 测试计数器错误,调用成功
*/
@Test
public void test_counter_error(){
init(0);
DubboAppender.doStart();
DubboAppender.clear();
ReferenceCountExchangeClient client = getReferenceClient(helloServiceInvoker);
//close一次,计数器从2减少到1,不能warning
client.close();
Assert.assertEquals("hello", helloService.hello());
Assert.assertEquals("should not warning message", 0, LogUtil.findMessage(errorMsg));
//计数器错误,调用正常
client.close();
Assert.assertEquals("hello", helloService.hello());
Assert.assertEquals("should warning message", 1, LogUtil.findMessage(errorMsg));
//调用5千次输出一个错误
Assert.assertEquals("hello", helloService.hello());
Assert.assertEquals("should warning message", 1, LogUtil.findMessage(errorMsg));
DubboAppender.doStop();
//重新调用一次后status已经是available.
Assert.assertEquals("client status available", true, helloServiceInvoker.isAvailable());
client.close();
//client已经被替换为lazyclient lazy client从referenceclientmap中获取,获取到的是上次的client(已经被调用过一次),所以close状态为false
Assert.assertEquals("client status close", false, client.isClosed());
Assert.assertEquals("client status close", false, helloServiceInvoker.isAvailable());
destoy();
}
@SuppressWarnings("unchecked")
private void init(int connections){
int port = NetUtils.getAvailablePort();
URL demoUrl = URL.valueOf("dubbo://127.0.0.1:"+port+"/demo?"+Constants.CONNECTIONS_KEY+"="+connections);
URL helloUrl = URL.valueOf("dubbo://127.0.0.1:"+port+"/hello?"+Constants.CONNECTIONS_KEY+"="+connections);
demoExporter = export(new DemoServiceImpl(), IDemoService.class, demoUrl);
helloExporter = export(new HelloServiceImpl(), IHelloService.class, helloUrl);
demoServiceInvoker = (Invoker<IDemoService>) referInvoker(IDemoService.class, demoUrl);
demoService = proxy.getProxy(demoServiceInvoker);
Assert.assertEquals("demo", demoService.demo());
helloServiceInvoker = (Invoker<IHelloService>) referInvoker(IHelloService.class, helloUrl);
helloService = proxy.getProxy(helloServiceInvoker);
Assert.assertEquals("hello", helloService.hello());
demoClient = getClient(demoServiceInvoker);
helloClient = getClient(helloServiceInvoker);
}
private void destoy(){
demoServiceInvoker.destroy();
helloServiceInvoker.destroy();
demoExporter.getInvoker().destroy();
helloExporter.getInvoker().destroy();
}
private ExchangeClient getClient(Invoker<?> invoker){
if (invoker.getUrl().getParameter(Constants.CONNECTIONS_KEY, 1) == 1){
return getInvokerClient(invoker);
} else {
ReferenceCountExchangeClient client = getReferenceClient(invoker);
try {
Field clientField = ReferenceCountExchangeClient.class.getDeclaredField("client");
clientField.setAccessible(true);
return (ExchangeClient) clientField.get(client);
} catch (Exception e) {
e.printStackTrace();
Assert.fail(e.getMessage());
throw new RuntimeException(e);
}
}
}
private ReferenceCountExchangeClient getReferenceClient(Invoker<?> invoker){
return (ReferenceCountExchangeClient)getInvokerClient(invoker);
}
private ExchangeClient getInvokerClient(Invoker<?> invoker){
@SuppressWarnings("rawtypes")
DubboInvoker dInvoker = (DubboInvoker)invoker;
try {
Field clientField = DubboInvoker.class.getDeclaredField("clients");
clientField.setAccessible(true);
ExchangeClient[] clients = (ExchangeClient[]) clientField.get(dInvoker);
return clients[0];
} catch (Exception e) {
e.printStackTrace();
Assert.fail(e.getMessage());
throw new RuntimeException(e);
}
}
private static DubboProtocol protocol = DubboProtocol.getDubboProtocol();
public static ProxyFactory proxy = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
public static Invoker<?> referInvoker(Class<?> type, URL url) {
return (Invoker<?>)protocol.refer(type, url);
}
public static <T> Exporter<T> export(T instance, Class<T> type, String url) {
return export(instance, type, URL.valueOf(url));
}
public static <T> Exporter<T> export(T instance, Class<T> type, URL url) {
return protocol.export(proxy.getInvoker(instance, type, url));
}
}