/*
* Copyright 2009-2016 Weibo, Inc.
*
* 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.weibo.api.motan.cluster;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import junit.framework.Assert;
import org.jmock.Expectations;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.jmock.lib.legacy.ClassImposteriser;
import org.junit.Before;
import org.junit.Test;
import com.weibo.api.motan.cluster.support.ClusterSupport;
import com.weibo.api.motan.common.MotanConstants;
import com.weibo.api.motan.common.URLParamType;
import com.weibo.api.motan.protocol.example.IHello;
import com.weibo.api.motan.registry.NotifyListener;
import com.weibo.api.motan.registry.Registry;
import com.weibo.api.motan.registry.RegistryService;
import com.weibo.api.motan.rpc.Protocol;
import com.weibo.api.motan.rpc.Referer;
import com.weibo.api.motan.rpc.URL;
import com.weibo.api.motan.util.NetUtils;
import com.weibo.api.motan.util.StringTools;
/**
*
* ClusterSupport test.
*
* @author fishermen
* @version V1.0 created at: 2013-6-22
*/
public class ClusterSupportTest {
private static JUnit4Mockery mockery = new JUnit4Mockery() {
{
setImposteriser(ClassImposteriser.INSTANCE);
}
};
private static ClusterSupport<IHello> clusterSupport;
private static Protocol protocol = mockery.mock(Protocol.class);
private static Map<String, Registry> registries = new HashMap<String, Registry>();
private static String regProtocol1 = "reg_1";
private static String regProtocol2 = "reg_2";
private static String localAddress = NetUtils.getLocalAddress().getHostAddress();
private static Map<String, Referer<IHello>> portReferers = new HashMap<String, Referer<IHello>>();
@Before
public void initCluster() {
clusterSupport = new ClusterSupportMask<IHello>(IHello.class, mockRegistryUrls());
registries.put(regProtocol1, mockery.mock(Registry.class, regProtocol1));
registries.put(regProtocol2, mockery.mock(Registry.class, regProtocol2));
mockery.checking(new Expectations() {
{
allowing(any(Registry.class)).method("register").with(any(URL.class));
allowing(any(Registry.class)).method("subscribe").with(any(URL.class), any(NotifyListener.class));
}
});
clusterSupport.init();
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Test
public void testNotify() {
// 先利用registry1 通知新增2个url
final int urlsCount = 5;
final List<URL> serviceUrls1 = new ArrayList<URL>();
for (int i = 0; i < urlsCount; i++) {
URL url = new URL(MotanConstants.PROTOCOL_MOTAN, localAddress, 1000 + i, IHello.class.getName());
url.addParameter(URLParamType.nodeType.getName(), MotanConstants.NODE_TYPE_SERVICE);
serviceUrls1.add(url);
}
final URL reg1Url = new URL("reg_protocol_1", NetUtils.getLocalAddress().getHostAddress(), 0, RegistryService.class.getName());
final URL reg2Url = new URL("reg_protocol_2", NetUtils.getLocalAddress().getHostAddress(), 0, RegistryService.class.getName());
mockery.checking(new Expectations() {
{
for (int i = 0; i < urlsCount; i++) {
URL serviceUrl = serviceUrls1.get(i).createCopy();
URL refererUrl = serviceUrls1.get(i).createCopy();
String application = serviceUrl.getParameter(URLParamType.application.getName(), URLParamType.application.getValue());
String module = serviceUrl.getParameter(URLParamType.module.getName(), URLParamType.module.getValue());
refererUrl.addParameters(serviceUrl.getParameters());
refererUrl.addParameter(URLParamType.application.getName(), application);
refererUrl.addParameter(URLParamType.module.getName(), module);
refererUrl.addParameter(URLParamType.check.getName(), "false");
atLeast(1).of(protocol).refer(IHello.class, refererUrl, serviceUrl);
will(returnValue(mockReferer(refererUrl)));
atLeast(1).of(mockReferer(refererUrl)).getUrl();
will(returnValue(serviceUrls1.get(i)));
atLeast(1).of(mockReferer(refererUrl)).getServiceUrl();
will(returnValue(serviceUrls1.get(i)));
}
for (int i = 0; i < 3; i++) {
atLeast(1).of(mockReferer(serviceUrls1.get(i))).destroy();
}
atLeast(1).of(registries.get(regProtocol1)).getUrl();
will(returnValue(reg1Url));
atLeast(1).of(registries.get(regProtocol2)).getUrl();
will(returnValue(reg2Url));
}
});
List copy = new ArrayList<URL>();
clusterSupport.notify(registries.get(regProtocol1).getUrl(), copy(copy, serviceUrls1.subList(0, 2)));
Assert.assertEquals(clusterSupport.getCluster().getReferers().size(), 2);
// 再利用registry1 通知有三个
clusterSupport.notify(registries.get(regProtocol1).getUrl(), copy(copy, serviceUrls1.subList(0, 3)));
Assert.assertEquals(clusterSupport.getCluster().getReferers().size(), 3);
// 再利用registr1 通知有0个
clusterSupport.notify(registries.get(regProtocol1).getUrl(), copy(copy, serviceUrls1.subList(0, 0)));
Assert.assertEquals(clusterSupport.getCluster().getReferers().size(), 3);
// 再利用registr1 通知有2个,少了一个
clusterSupport.notify(registries.get(regProtocol1).getUrl(), copy(copy, serviceUrls1.subList(1, 3)));
Assert.assertEquals(clusterSupport.getCluster().getReferers().size(), 2);
// 再利用registry1 通知有三个
clusterSupport.notify(registries.get(regProtocol1).getUrl(), copy(copy, serviceUrls1.subList(0, 3)));
Assert.assertEquals(clusterSupport.getCluster().getReferers().size(), 3);
// 利用registry2,通知有2个
clusterSupport.notify(registries.get(regProtocol2).getUrl(), copy(copy, serviceUrls1.subList(3, 5)));
Assert.assertEquals(clusterSupport.getCluster().getReferers().size(), 5);
// 再利用registr1 通知有2个,少了一个
clusterSupport.notify(registries.get(regProtocol1).getUrl(), copy(copy, serviceUrls1.subList(1, 3)));
Assert.assertEquals(clusterSupport.getCluster().getReferers().size(), 4);
// 再利用registr1 通知有registry1没有url了
clusterSupport.notify(registries.get(regProtocol1).getUrl(), null);
Assert.assertEquals(clusterSupport.getCluster().getReferers().size(), 2);
List<Referer<IHello>> oldReferers = clusterSupport.getCluster().getReferers();
// 利用registry2,通知有2个
clusterSupport.notify(registries.get(regProtocol2).getUrl(), copy(copy, serviceUrls1.subList(3, 5)));
Assert.assertEquals(clusterSupport.getCluster().getReferers().size(), 2);
for (Referer<IHello> referer : clusterSupport.getCluster().getReferers()) {
if (!oldReferers.contains(referer)) {
Assert.assertTrue(false);
}
}
}
private static List<URL> mockRegistryUrls() {
URL refUrl = new URL(MotanConstants.PROTOCOL_MOTAN, NetUtils.getLocalAddress().getHostAddress(), 0, IHello.class.getName());
refUrl.addParameter(URLParamType.check.getName(), "false");
URL url1 = new URL(regProtocol1, "192.168.1.1", 18081, RegistryService.class.getName());
url1.addParameter(URLParamType.embed.getName(), StringTools.urlEncode(refUrl.toFullStr()));
URL url2 = new URL(regProtocol2, "192.168.1.2", 8082, RegistryService.class.getName());
url2.addParameter(URLParamType.embed.getName(), StringTools.urlEncode(refUrl.toFullStr()));
List<URL> urls = new ArrayList<URL>();
urls.add(url1);
urls.add(url2);
return urls;
}
private static class ClusterSupportMask<T> extends ClusterSupport<T> {
public ClusterSupportMask(Class<T> interfaceClass, List<URL> registryUrls) {
super(interfaceClass, registryUrls);
}
@Override
protected Protocol getDecorateProtocol(String protocolName) {
return protocol;
}
@Override
protected Registry getRegistry(URL url) {
return registries.get(url.getProtocol());
}
}
@SuppressWarnings("unchecked")
private synchronized Referer<IHello> mockReferer(URL url) {
if (portReferers.get(url.getIdentity()) != null) {
return portReferers.get(url.getIdentity());
}
portReferers.put(url.getIdentity(), mockery.mock(Referer.class, url.getIdentity()));
return portReferers.get(url.getIdentity());
}
private List<URL> copy(List<URL> dest, List<URL> source) {
dest.clear();
for (URL url : source) {
dest.add(url.createCopy());
}
return dest;
}
}