From a4eb10d1dac20be1cd6fcf734a3e6817530c00c4 Mon Sep 17 00:00:00 2001 From: Ming Deng Date: Mon, 6 May 2019 09:11:15 +0800 Subject: [PATCH] 1. Add unit tests for cluster-consul-plugin; (#2572) 2. Add unit tests for cluster-zookeeper-plugin; 3. Add unit tests for cluster-kubernetes-plugin; --- .../consul/ClusterModuleConsulProvider.java | 11 +- .../ClusterModuleConsulProviderTest.java | 142 +++++++++++++ .../plugin/consul/ConsulCoordinatorTest.java | 201 ++++++++++++++++++ .../NamespacedPodListWatchTest.java | 166 +++++++++++++++ .../plugin/zookeeper/NodeNameBuilderTest.java | 36 ++++ .../zookeeper/ZookeeperCoordinatorTest.java | 101 +++++++++ 6 files changed, 654 insertions(+), 3 deletions(-) create mode 100644 oap-server/server-cluster-plugin/cluster-consul-plugin/src/test/java/org/apache/skywalking/oap/server/cluster/plugin/consul/ClusterModuleConsulProviderTest.java create mode 100644 oap-server/server-cluster-plugin/cluster-consul-plugin/src/test/java/org/apache/skywalking/oap/server/cluster/plugin/consul/ConsulCoordinatorTest.java create mode 100644 oap-server/server-cluster-plugin/cluster-kubernetes-plugin/src/test/java/org/apache/skywalking/oap/server/cluster/plugin/kubernetes/dependencies/NamespacedPodListWatchTest.java create mode 100644 oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/test/java/org/apache/skywalking/oap/server/cluster/plugin/zookeeper/NodeNameBuilderTest.java create mode 100644 oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/test/java/org/apache/skywalking/oap/server/cluster/plugin/zookeeper/ZookeeperCoordinatorTest.java diff --git a/oap-server/server-cluster-plugin/cluster-consul-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/consul/ClusterModuleConsulProvider.java b/oap-server/server-cluster-plugin/cluster-consul-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/consul/ClusterModuleConsulProvider.java index 61458bb1f..d6fd2cc36 100644 --- a/oap-server/server-cluster-plugin/cluster-consul-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/consul/ClusterModuleConsulProvider.java +++ b/oap-server/server-cluster-plugin/cluster-consul-plugin/src/main/java/org/apache/skywalking/oap/server/cluster/plugin/consul/ClusterModuleConsulProvider.java @@ -20,6 +20,7 @@ package org.apache.skywalking.oap.server.cluster.plugin.consul; import com.google.common.net.HostAndPort; import com.orbitz.consul.Consul; +import com.orbitz.consul.ConsulException; import org.apache.skywalking.oap.server.core.CoreModule; import org.apache.skywalking.oap.server.core.cluster.ClusterModule; import org.apache.skywalking.oap.server.core.cluster.ClusterNodesQuery; @@ -71,12 +72,16 @@ public class ClusterModuleConsulProvider extends ModuleProvider { hostAndPorts.add(HostAndPort.fromParts(address.getHost(), address.getPort())); } + Consul.Builder consulBuilder = Consul.builder() +// we should set this value or it will be blocked forever + .withConnectTimeoutMillis(3000); + if (hostAndPorts.size() > 1) { - client = Consul.builder().withMultipleHostAndPort(hostAndPorts, 5000).build(); + client = consulBuilder.withMultipleHostAndPort(hostAndPorts, 5000).build(); } else { - client = Consul.builder().withHostAndPort(hostAndPorts.get(0)).build(); + client = consulBuilder.withHostAndPort(hostAndPorts.get(0)).build(); } - } catch (ConnectStringParseException e) { + } catch (ConnectStringParseException | ConsulException e) { throw new ModuleStartException(e.getMessage(), e); } diff --git a/oap-server/server-cluster-plugin/cluster-consul-plugin/src/test/java/org/apache/skywalking/oap/server/cluster/plugin/consul/ClusterModuleConsulProviderTest.java b/oap-server/server-cluster-plugin/cluster-consul-plugin/src/test/java/org/apache/skywalking/oap/server/cluster/plugin/consul/ClusterModuleConsulProviderTest.java new file mode 100644 index 000000000..8a14d430d --- /dev/null +++ b/oap-server/server-cluster-plugin/cluster-consul-plugin/src/test/java/org/apache/skywalking/oap/server/cluster/plugin/consul/ClusterModuleConsulProviderTest.java @@ -0,0 +1,142 @@ +/* + * 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.skywalking.oap.server.cluster.plugin.consul; + +import com.google.common.collect.Lists; +import com.google.common.net.HostAndPort; +import com.orbitz.consul.Consul; +import org.apache.skywalking.oap.server.core.CoreModule; +import org.apache.skywalking.oap.server.core.cluster.ClusterModule; +import org.apache.skywalking.oap.server.library.module.ModuleConfig; +import org.apache.skywalking.oap.server.library.module.ModuleStartException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.reflect.Whitebox; + +import java.util.Collection; +import java.util.List; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +/** + * Created by dengming, 2019.05.01 + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest(Consul.class) +@PowerMockIgnore("javax.management.*") +public class ClusterModuleConsulProviderTest { + + private ClusterModuleConsulProvider provider = new ClusterModuleConsulProvider(); + + @Test + public void name() { + assertEquals("consul", provider.name()); + } + + @Test + public void module() { + assertEquals(ClusterModule.class, provider.module()); + } + + @Test + public void createConfigBeanIfAbsent() { + ModuleConfig moduleConfig = provider.createConfigBeanIfAbsent(); + assertTrue(moduleConfig instanceof ClusterModuleConsulConfig); + } + + @Test(expected = ModuleStartException.class) + public void prepareWithNonHost() throws Exception { + provider.prepare(); + } + + @Test + @SuppressWarnings("unchecked") + public void prepare() throws Exception { + ClusterModuleConsulConfig consulConfig = new ClusterModuleConsulConfig(); + consulConfig.setHostPort("10.0.0.1:1000,10.0.0.2:1001"); + Whitebox.setInternalState(provider, "config", consulConfig); + + Consul consulClient = mock(Consul.class); + Consul.Builder builder = mock(Consul.Builder.class); + when(builder.build()).thenReturn(consulClient); + + PowerMockito.mockStatic(Consul.class); + when(Consul.builder()).thenReturn(builder); + when(builder.withConnectTimeoutMillis(anyLong())).thenReturn(builder); + + when(builder.withMultipleHostAndPort(anyCollection(), anyLong())).thenReturn(builder); + provider.prepare(); + + ArgumentCaptor addressCaptor = ArgumentCaptor.forClass(Collection.class); + ArgumentCaptor timeCaptor = ArgumentCaptor.forClass(long.class); + verify(builder).withMultipleHostAndPort(addressCaptor.capture(), timeCaptor.capture()); + + List address = (List) addressCaptor.getValue(); + assertEquals(2, address.size()); + assertEquals(Lists.newArrayList(HostAndPort.fromParts("10.0.0.1", 1000), + HostAndPort.fromParts("10.0.0.2", 1001) + ), address); + } + + @Test + public void prepareSingle() throws Exception { + ClusterModuleConsulConfig consulConfig = new ClusterModuleConsulConfig(); + consulConfig.setHostPort("10.0.0.1:1000"); + Whitebox.setInternalState(provider, "config", consulConfig); + + Consul consulClient = mock(Consul.class); + Consul.Builder builder = mock(Consul.Builder.class); + when(builder.build()).thenReturn(consulClient); + + PowerMockito.mockStatic(Consul.class); + when(Consul.builder()).thenReturn(builder); + when(builder.withConnectTimeoutMillis(anyLong())).thenCallRealMethod(); + + when(builder.withHostAndPort(any())).thenReturn(builder); + + provider.prepare(); + + ArgumentCaptor hostAndPortArgumentCaptor = ArgumentCaptor.forClass(HostAndPort.class); + verify(builder).withHostAndPort(hostAndPortArgumentCaptor.capture()); + + HostAndPort address = hostAndPortArgumentCaptor.getValue(); + assertEquals(HostAndPort.fromParts("10.0.0.1", 1000), address); + } + + @Test + public void start() { + provider.start(); + } + + @Test + public void notifyAfterCompleted() { + provider.notifyAfterCompleted(); + } + + @Test + public void requiredModules() { + String[] modules = provider.requiredModules(); + assertArrayEquals(new String[]{CoreModule.NAME}, modules); + } +} \ No newline at end of file diff --git a/oap-server/server-cluster-plugin/cluster-consul-plugin/src/test/java/org/apache/skywalking/oap/server/cluster/plugin/consul/ConsulCoordinatorTest.java b/oap-server/server-cluster-plugin/cluster-consul-plugin/src/test/java/org/apache/skywalking/oap/server/cluster/plugin/consul/ConsulCoordinatorTest.java new file mode 100644 index 000000000..181e00393 --- /dev/null +++ b/oap-server/server-cluster-plugin/cluster-consul-plugin/src/test/java/org/apache/skywalking/oap/server/cluster/plugin/consul/ConsulCoordinatorTest.java @@ -0,0 +1,201 @@ +/* + * 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.skywalking.oap.server.cluster.plugin.consul; + +import com.orbitz.consul.AgentClient; +import com.orbitz.consul.Consul; +import com.orbitz.consul.HealthClient; +import com.orbitz.consul.model.ConsulResponse; +import com.orbitz.consul.model.agent.Registration; +import com.orbitz.consul.model.health.Service; +import com.orbitz.consul.model.health.ServiceHealth; +import org.apache.skywalking.oap.server.core.cluster.RemoteInstance; +import org.apache.skywalking.oap.server.core.remote.client.Address; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +/** + * Created by dengming, 2019.05.02 + */ +public class ConsulCoordinatorTest { + + private Consul consul = mock(Consul.class); + + private ClusterModuleConsulConfig consulConfig = new ClusterModuleConsulConfig(); + + private ConsulCoordinator coordinator; + + private ConsulResponse> consulResponse; + + private Address remoteAddress = new Address("10.0.0.1", 1000, false); + private Address selfRemoteAddress = new Address("10.0.0.2", 1001, true); + + private Address internalAddress = new Address("10.0.0.3", 1002, false); + + private AgentClient agentClient = mock(AgentClient.class); + + private static final String SERVICE_NAME = "my-service"; + + @Before + public void setUp() { + + consulConfig.setServiceName(SERVICE_NAME); + + coordinator = new ConsulCoordinator(consulConfig, consul); + + consulResponse = mock(ConsulResponse.class); + + HealthClient healthClient = mock(HealthClient.class); + when(healthClient.getHealthyServiceInstances(anyString())).thenReturn(consulResponse); + + when(consul.healthClient()).thenReturn(healthClient); + when(consul.agentClient()).thenReturn(agentClient); + } + + + @Test + @SuppressWarnings("unchecked") + public void queryRemoteNodesWithNonOrEmpty() { + when(consulResponse.getResponse()).thenReturn(null, Collections.emptyList()); + assertEquals(0, coordinator.queryRemoteNodes().size()); + assertEquals(0, coordinator.queryRemoteNodes().size()); + } + + @Test + public void queryRemoteNodes() { + registerSelfRemote(); + List serviceHealths = mockHealth(); + when(consulResponse.getResponse()).thenReturn(serviceHealths); + List remoteInstances = coordinator.queryRemoteNodes(); + assertEquals(2, remoteInstances.size()); + + RemoteInstance selfInstance = remoteInstances.get(0); + velidate(selfRemoteAddress, selfInstance); + + RemoteInstance notSelfInstance = remoteInstances.get(1); + velidate(remoteAddress, notSelfInstance); + } + + @Test + public void queryRemoteNodesWithNullSelf() { + List serviceHealths = mockHealth(); + when(consulResponse.getResponse()).thenReturn(serviceHealths); + List remoteInstances = coordinator.queryRemoteNodes(); + assertTrue(remoteInstances.isEmpty()); + } + + @Test + public void registerRemote() { + registerRemote(remoteAddress); + } + + @Test + public void registerSelfRemote() { + registerRemote(selfRemoteAddress); + } + + @Test + public void registerRemoteUsingInternal() { + consulConfig.setInternalComHost(internalAddress.getHost()); + consulConfig.setInternalComPort(internalAddress.getPort()); + registerRemote(internalAddress); + } + + private void velidate(Address originArress, RemoteInstance instance) { + Address instanceAddress = instance.getAddress(); + assertEquals(originArress.getHost(), instanceAddress.getHost()); + assertEquals(originArress.getPort(), instanceAddress.getPort()); + } + + private void registerRemote(Address address) { + coordinator.registerRemote(new RemoteInstance(address)); + Registration registration = afterRegister(); + verifyRegistration(address, registration); + } + + private Registration afterRegister() { + ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Registration.class); + verify(agentClient).register(argumentCaptor.capture()); + return argumentCaptor.getValue(); + } + + private void verifyRegistration(Address remoteAddress, Registration registration) { + assertNotNull(registration); + assertEquals(SERVICE_NAME, registration.getName()); + assertEquals(remoteAddress.getHost() + "_" + remoteAddress.getPort(), registration.getId()); + assertTrue(registration.getAddress().isPresent()); + assertEquals(remoteAddress.getHost(), registration.getAddress().get()); + assertTrue(registration.getPort().isPresent()); + assertEquals(remoteAddress.getPort(), registration.getPort().get().intValue()); + assertTrue(registration.getCheck().isPresent()); + Registration.RegCheck regCheck = registration.getCheck().get(); + assertTrue(regCheck.getGrpc().isPresent()); + assertEquals(remoteAddress.getHost() + ":" + remoteAddress.getPort(), regCheck.getGrpc().get()); + } + + private List mockHealth() { + List result = new LinkedList<>(); + result.add(mockSelfService()); + result.add(mockNotSelfService()); + result.add(mockNullServiceAddress()); + return result; + } + + private ServiceHealth mockNotSelfService() { + ServiceHealth serviceHealth = mock(ServiceHealth.class); + Service service = mock(Service.class); + + when(service.getAddress()).thenReturn(remoteAddress.getHost()); + when(service.getPort()).thenReturn(remoteAddress.getPort()); + + when(serviceHealth.getService()).thenReturn(service); + + return serviceHealth; + } + + private ServiceHealth mockSelfService() { + ServiceHealth serviceHealth = mock(ServiceHealth.class); + Service service = mock(Service.class); + + when(service.getAddress()).thenReturn(selfRemoteAddress.getHost()); + when(service.getPort()).thenReturn(selfRemoteAddress.getPort()); + + when(serviceHealth.getService()).thenReturn(service); + + return serviceHealth; + } + + private ServiceHealth mockNullServiceAddress() { + ServiceHealth serviceHealth = mock(ServiceHealth.class); + Service service = mock(Service.class); + + when(serviceHealth.getService()).thenReturn(service); + + when(service.getAddress()).thenReturn(""); + + return serviceHealth; + } +} \ No newline at end of file diff --git a/oap-server/server-cluster-plugin/cluster-kubernetes-plugin/src/test/java/org/apache/skywalking/oap/server/cluster/plugin/kubernetes/dependencies/NamespacedPodListWatchTest.java b/oap-server/server-cluster-plugin/cluster-kubernetes-plugin/src/test/java/org/apache/skywalking/oap/server/cluster/plugin/kubernetes/dependencies/NamespacedPodListWatchTest.java new file mode 100644 index 000000000..71d8b5d01 --- /dev/null +++ b/oap-server/server-cluster-plugin/cluster-kubernetes-plugin/src/test/java/org/apache/skywalking/oap/server/cluster/plugin/kubernetes/dependencies/NamespacedPodListWatchTest.java @@ -0,0 +1,166 @@ +/* + * 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.skywalking.oap.server.cluster.plugin.kubernetes.dependencies; + +import com.squareup.okhttp.Call; +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.Request; +import io.kubernetes.client.ApiClient; +import io.kubernetes.client.models.V1ObjectMeta; +import io.kubernetes.client.models.V1Pod; +import io.kubernetes.client.models.V1PodStatus; +import io.kubernetes.client.util.Watch; +import org.apache.skywalking.oap.server.cluster.plugin.kubernetes.Event; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.reflect.Whitebox; + +import java.lang.reflect.Type; +import java.util.Iterator; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +/** + * Created by dengming, 2019.05.02 + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest({Watch.class, OkHttpClient.class}) +@PowerMockIgnore("javax.management.*") +public class NamespacedPodListWatchTest { + + private NamespacedPodListWatch namespacedPodListWatch; + + private Watch mockWatch = mock(Watch.class); + + private static final String NAME_SPACE = "my-namespace"; + private static final String LABEL_SELECTOR = "equality-based"; + private static final String RESPONSE_TYPE = "my-type"; + private static final int WATCH_TIMEOUT_SECONDS = 3; + + + @Before + public void setUp() throws Exception { + + namespacedPodListWatch = new NamespacedPodListWatch(NAME_SPACE, LABEL_SELECTOR, WATCH_TIMEOUT_SECONDS); + + PowerMockito.mockStatic(Watch.class); + when(Watch.createWatch(any(), any(), any())).thenReturn(mockWatch); + Call mockCall = mock(Call.class); + PowerMockito.whenNew(Call.class).withArguments(any(OkHttpClient.class), any(Request.class)).thenReturn(mockCall); + + namespacedPodListWatch.initOrReset(); + + ArgumentCaptor apiClientArgumentCaptor = ArgumentCaptor.forClass(ApiClient.class); + ArgumentCaptor callArgumentCaptor = ArgumentCaptor.forClass(Call.class); + ArgumentCaptor typeArgumentCaptor = ArgumentCaptor.forClass(Type.class); + + PowerMockito.verifyStatic(); + Watch.createWatch( + apiClientArgumentCaptor.capture(), + callArgumentCaptor.capture(), + typeArgumentCaptor.capture()); + + ApiClient apiClient = apiClientArgumentCaptor.getValue(); + Call call = callArgumentCaptor.getValue(); + Type type = typeArgumentCaptor.getValue(); + + assertEquals(mockCall, call); + assertNotNull(apiClient); + assertNotNull(type); + + } + + @Test + public void iterator() { + when(mockWatch.hasNext()).thenReturn(true, true, false); + Iterator mockIterator = mockIterator(); + when(mockWatch.iterator()).thenReturn(mockIterator); + Iterator iterator = namespacedPodListWatch.iterator(); + + assertNotNull(iterator); + assertTrue(iterator.hasNext()); + + Event event0 = iterator.next(); + assertNotNull(event0); + validateEvent(event0, 0); + + assertTrue(iterator.hasNext()); + Event event1 = iterator.next(); + assertNotNull(event1); + validateEvent(event1, 1); + + assertFalse(iterator.hasNext()); + + } + + @Test + public void iteratorWithEmpty() { + Iterator iterator = mock(Iterator.class); + when(iterator.hasNext()).thenReturn(false); + when(mockWatch.iterator()).thenReturn(iterator); + + Iterator eventIterator = namespacedPodListWatch.iterator(); + assertFalse(eventIterator.hasNext()); + } + + + private Iterator> mockIterator() { + Iterator> iterator = mock(Iterator.class); + + when(iterator.hasNext()).thenReturn(true, true, false); + Watch.Response response0 = mockResponse(0); + Watch.Response response1 = mockResponse(1); + + when(iterator.next()).thenReturn(response0, response1); + + return iterator; + } + + private Watch.Response mockResponse(int i) { + V1Pod v1Pod = new V1Pod(); + V1ObjectMeta meta = new V1ObjectMeta(); + V1PodStatus status = new V1PodStatus(); + status.setPodIP("PodIp" + i); + meta.setUid("uid" + i); + v1Pod.setMetadata(meta); + v1Pod.setStatus(status); + Watch.Response response = mock(Watch.Response.class); + response.object = v1Pod; + response.type = RESPONSE_TYPE; + return response; + } + + private void validateEvent(Event event, int i) { + String type = Whitebox.getInternalState(event, "type"); + assertEquals(RESPONSE_TYPE, type); + + String uid = Whitebox.getInternalState(event, "uid"); + assertEquals("uid" + i, uid); + + String host = Whitebox.getInternalState(event, "host"); + assertEquals("PodIp" + i, host); + } + +} \ No newline at end of file diff --git a/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/test/java/org/apache/skywalking/oap/server/cluster/plugin/zookeeper/NodeNameBuilderTest.java b/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/test/java/org/apache/skywalking/oap/server/cluster/plugin/zookeeper/NodeNameBuilderTest.java new file mode 100644 index 000000000..6d7d18502 --- /dev/null +++ b/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/test/java/org/apache/skywalking/oap/server/cluster/plugin/zookeeper/NodeNameBuilderTest.java @@ -0,0 +1,36 @@ +/* + * 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.skywalking.oap.server.cluster.plugin.zookeeper; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Created by dengming, 2019.05.02 + */ +public class NodeNameBuilderTest { + + @Test + public void build() { + String moduleName = "my-module"; + String providerName = "my-provider-name"; + String nodeName = NodeNameBuilder.build(moduleName, providerName); + assertEquals(moduleName + "/" + providerName, nodeName); + } +} \ No newline at end of file diff --git a/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/test/java/org/apache/skywalking/oap/server/cluster/plugin/zookeeper/ZookeeperCoordinatorTest.java b/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/test/java/org/apache/skywalking/oap/server/cluster/plugin/zookeeper/ZookeeperCoordinatorTest.java new file mode 100644 index 000000000..cc7e58aef --- /dev/null +++ b/oap-server/server-cluster-plugin/cluster-zookeeper-plugin/src/test/java/org/apache/skywalking/oap/server/cluster/plugin/zookeeper/ZookeeperCoordinatorTest.java @@ -0,0 +1,101 @@ +/* + * 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.skywalking.oap.server.cluster.plugin.zookeeper; + +import com.google.common.base.Strings; +import org.apache.curator.x.discovery.ServiceCache; +import org.apache.curator.x.discovery.ServiceCacheBuilder; +import org.apache.curator.x.discovery.ServiceDiscovery; +import org.apache.curator.x.discovery.ServiceInstance; +import org.apache.skywalking.oap.server.core.cluster.RemoteInstance; +import org.apache.skywalking.oap.server.core.remote.client.Address; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +/** + * Created by dengming, 2019.05.02 + */ +public class ZookeeperCoordinatorTest { + + private ClusterModuleZookeeperConfig config = new ClusterModuleZookeeperConfig(); + + private ServiceDiscovery serviceDiscovery = mock(ServiceDiscovery.class); + + private ServiceCacheBuilder cacheBuilder = mock(ServiceCacheBuilder.class); + + private ServiceCache serviceCache = mock(ServiceCache.class); + + private ZookeeperCoordinator coordinator; + + private Address address = new Address("127.0.0.2", 10001, false); + + private Address selfAddress = new Address("127.0.0.1", 1000, true); + + @Before + public void setUp() throws Exception { + config.setHostPort(address.getHost() + ":" + address.getPort()); + coordinator = new ZookeeperCoordinator(config, serviceDiscovery); + when(serviceDiscovery.serviceCacheBuilder()).thenReturn(cacheBuilder); + when(cacheBuilder.name("remote")).thenReturn(cacheBuilder); + when(cacheBuilder.build()).thenReturn(serviceCache); + doNothing().when(serviceCache).start(); + + doNothing().when(serviceDiscovery).registerService(any()); + } + + @Test + public void registerRemote() throws Exception { + config.setInternalComHost(selfAddress.getHost()); + config.setInternalComPort(selfAddress.getPort()); + RemoteInstance instance = new RemoteInstance(address); + coordinator.registerRemote(instance); + validateServiceInstance(selfAddress, new RemoteInstance(selfAddress)); + } + + @Test + public void registerRemoteNoNeedInternal() throws Exception { + RemoteInstance instance = new RemoteInstance(address); + coordinator.registerRemote(instance); + validateServiceInstance(address, instance); + } + + @SuppressWarnings("unchecked") + private void validateServiceInstance(Address address, RemoteInstance instance) throws Exception { + ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(ServiceInstance.class); + verify(serviceDiscovery).registerService(argumentCaptor.capture()); + + ServiceInstance serviceInstance = argumentCaptor.getValue(); + + assertEquals("remote", serviceInstance.getName()); + assertTrue(!Strings.isNullOrEmpty(serviceInstance.getId())); + assertEquals(address.getHost(), serviceInstance.getAddress()); + assertEquals(address.getPort(), serviceInstance.getPort().intValue()); + + RemoteInstance payload = serviceInstance.getPayload(); + assertEquals(payload.getAddress(), instance.getAddress()); + + } + + @Test + public void queryRemoteNodes() { + } +} \ No newline at end of file