blob: 090c93a466877f87101a52509eaf20c9c7bbc084 [file] [log] [blame]
/*
* 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 org.apache.dubbo.rpc.cluster.router.mesh.route;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.rpc.cluster.governance.GovernanceRuleRepository;
import org.apache.dubbo.rpc.cluster.router.mesh.util.MeshRuleListener;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ModuleModel;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.SafeConstructor;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
class MeshRuleManagerTest {
private static final String rule1 = "apiVersion: service.dubbo.apache.org/v1alpha1\n" + "kind: DestinationRule\n"
+ "metadata: { name: demo-route.Type1 }\n"
+ "spec:\n"
+ " host: demo\n"
+ "\n";
private static final String rule2 = "apiVersion: service.dubbo.apache.org/v1alpha1\n" + "kind: VirtualService\n"
+ "metadata: { name: demo-route.Type1 }\n"
+ "spec:\n"
+ " hosts: [demo]\n";
private static final String rule3 = "apiVersion: service.dubbo.apache.org/v1alpha1\n" + "kind: DestinationRule\n"
+ "metadata: { name: demo-route.Type2 }\n"
+ "spec:\n"
+ " host: demo\n"
+ "\n";
private static final String rule4 = "apiVersion: service.dubbo.apache.org/v1alpha1\n" + "kind: VirtualService\n"
+ "metadata: { name: demo-route.Type2 }\n"
+ "spec:\n"
+ " hosts: [demo]\n";
private ModuleModel originModule;
private ModuleModel moduleModel;
private GovernanceRuleRepository ruleRepository;
private Set<MeshEnvListenerFactory> envListenerFactories;
@BeforeEach
public void setup() {
originModule = ApplicationModel.defaultModel().getDefaultModule();
moduleModel = Mockito.spy(originModule);
ruleRepository = Mockito.mock(GovernanceRuleRepository.class);
when(moduleModel.getDefaultExtension(GovernanceRuleRepository.class)).thenReturn(ruleRepository);
ExtensionLoader<MeshEnvListenerFactory> envListenerFactoryLoader = Mockito.mock(ExtensionLoader.class);
envListenerFactories = new HashSet<>();
when(envListenerFactoryLoader.getSupportedExtensionInstances()).thenReturn(envListenerFactories);
when(moduleModel.getExtensionLoader(MeshEnvListenerFactory.class)).thenReturn(envListenerFactoryLoader);
}
@AfterEach
public void teardown() {
originModule.destroy();
}
@Test
void testRegister1() {
MeshRuleManager meshRuleManager = new MeshRuleManager(moduleModel);
MeshRuleListener meshRuleListener1 = new MeshRuleListener() {
@Override
public void onRuleChange(String appName, List<Map<String, Object>> rules) {
fail();
}
@Override
public void clearRule(String appName) {}
@Override
public String ruleSuffix() {
return "Type1";
}
};
meshRuleManager.register("dubbo-demo", meshRuleListener1);
assertEquals(1, meshRuleManager.getAppRuleListeners().size());
verify(ruleRepository, times(1)).getRule("dubbo-demo.MESHAPPRULE", "dubbo", 5000L);
MeshAppRuleListener meshAppRuleListener =
meshRuleManager.getAppRuleListeners().values().iterator().next();
verify(ruleRepository, times(1)).addListener("dubbo-demo.MESHAPPRULE", "dubbo", meshAppRuleListener);
meshRuleManager.register("dubbo-demo", meshRuleListener1);
assertEquals(1, meshRuleManager.getAppRuleListeners().size());
MeshRuleListener meshRuleListener2 = new MeshRuleListener() {
@Override
public void onRuleChange(String appName, List<Map<String, Object>> rules) {
fail();
}
@Override
public void clearRule(String appName) {}
@Override
public String ruleSuffix() {
return "Type2";
}
};
meshRuleManager.register("dubbo-demo", meshRuleListener2);
assertEquals(1, meshRuleManager.getAppRuleListeners().size());
assertEquals(
2, meshAppRuleListener.getMeshRuleDispatcher().getListenerMap().size());
meshRuleManager.unregister("dubbo-demo", meshRuleListener1);
assertEquals(1, meshRuleManager.getAppRuleListeners().size());
assertEquals(
1, meshAppRuleListener.getMeshRuleDispatcher().getListenerMap().size());
meshRuleManager.unregister("dubbo-demo", meshRuleListener2);
assertEquals(0, meshRuleManager.getAppRuleListeners().size());
verify(ruleRepository, times(1)).removeListener("dubbo-demo.MESHAPPRULE", "dubbo", meshAppRuleListener);
}
@Test
void testRegister2() {
MeshRuleManager meshRuleManager = new MeshRuleManager(moduleModel);
AtomicInteger invokeTimes = new AtomicInteger(0);
MeshRuleListener meshRuleListener = new MeshRuleListener() {
@Override
public void onRuleChange(String appName, List<Map<String, Object>> rules) {
assertEquals("dubbo-demo", appName);
Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptions()));
assertTrue(rules.contains(yaml.load(rule1)));
assertTrue(rules.contains(yaml.load(rule2)));
invokeTimes.incrementAndGet();
}
@Override
public void clearRule(String appName) {}
@Override
public String ruleSuffix() {
return "Type1";
}
};
when(ruleRepository.getRule("dubbo-demo.MESHAPPRULE", "dubbo", 5000L)).thenReturn(rule1 + "---\n" + rule2);
meshRuleManager.register("dubbo-demo", meshRuleListener);
assertEquals(1, meshRuleManager.getAppRuleListeners().size());
verify(ruleRepository, times(1)).getRule("dubbo-demo.MESHAPPRULE", "dubbo", 5000L);
verify(ruleRepository, times(1))
.addListener(
"dubbo-demo.MESHAPPRULE",
"dubbo",
meshRuleManager
.getAppRuleListeners()
.values()
.iterator()
.next());
assertEquals(1, invokeTimes.get());
meshRuleManager.register("dubbo-demo", meshRuleListener);
assertEquals(1, meshRuleManager.getAppRuleListeners().size());
}
@Test
void testRegister3() {
MeshEnvListenerFactory meshEnvListenerFactory1 = Mockito.mock(MeshEnvListenerFactory.class);
MeshEnvListenerFactory meshEnvListenerFactory2 = Mockito.mock(MeshEnvListenerFactory.class);
MeshEnvListener meshEnvListener1 = Mockito.mock(MeshEnvListener.class);
when(meshEnvListenerFactory1.getListener()).thenReturn(meshEnvListener1);
MeshEnvListener meshEnvListener2 = Mockito.mock(MeshEnvListener.class);
when(meshEnvListenerFactory2.getListener()).thenReturn(meshEnvListener2);
envListenerFactories.add(meshEnvListenerFactory1);
envListenerFactories.add(meshEnvListenerFactory2);
MeshRuleManager meshRuleManager = new MeshRuleManager(moduleModel);
MeshRuleListener meshRuleListener1 = new MeshRuleListener() {
@Override
public void onRuleChange(String appName, List<Map<String, Object>> rules) {
fail();
}
@Override
public void clearRule(String appName) {}
@Override
public String ruleSuffix() {
return "Type1";
}
};
when(meshEnvListener1.isEnable()).thenReturn(false);
when(meshEnvListener2.isEnable()).thenReturn(true);
meshRuleManager.register("dubbo-demo", meshRuleListener1);
assertEquals(1, meshRuleManager.getAppRuleListeners().size());
verify(ruleRepository, times(1)).getRule("dubbo-demo.MESHAPPRULE", "dubbo", 5000L);
MeshAppRuleListener meshAppRuleListener =
meshRuleManager.getAppRuleListeners().values().iterator().next();
verify(ruleRepository, times(1)).addListener("dubbo-demo.MESHAPPRULE", "dubbo", meshAppRuleListener);
verify(meshEnvListener2, times(1)).onSubscribe("dubbo-demo", meshAppRuleListener);
meshRuleManager.register("dubbo-demo", meshRuleListener1);
assertEquals(1, meshRuleManager.getAppRuleListeners().size());
MeshRuleListener meshRuleListener2 = new MeshRuleListener() {
@Override
public void onRuleChange(String appName, List<Map<String, Object>> rules) {
fail();
}
@Override
public void clearRule(String appName) {}
@Override
public String ruleSuffix() {
return "Type2";
}
};
meshRuleManager.register("dubbo-demo", meshRuleListener2);
assertEquals(1, meshRuleManager.getAppRuleListeners().size());
assertEquals(
2, meshAppRuleListener.getMeshRuleDispatcher().getListenerMap().size());
meshRuleManager.unregister("dubbo-demo", meshRuleListener1);
assertEquals(1, meshRuleManager.getAppRuleListeners().size());
assertEquals(
1, meshAppRuleListener.getMeshRuleDispatcher().getListenerMap().size());
meshRuleManager.unregister("dubbo-demo", meshRuleListener2);
assertEquals(0, meshRuleManager.getAppRuleListeners().size());
verify(ruleRepository, times(1)).removeListener("dubbo-demo.MESHAPPRULE", "dubbo", meshAppRuleListener);
verify(meshEnvListener2, times(1)).onUnSubscribe("dubbo-demo");
}
}