diff --git a/client/src/main/java/com/alibaba/nacos/client/constant/Constants.java b/client/src/main/java/com/alibaba/nacos/client/constant/Constants.java index 26922657f..baadcb02f 100644 --- a/client/src/main/java/com/alibaba/nacos/client/constant/Constants.java +++ b/client/src/main/java/com/alibaba/nacos/client/constant/Constants.java @@ -16,6 +16,8 @@ package com.alibaba.nacos.client.constant; +import java.util.concurrent.TimeUnit; + /** * All the constants. * @@ -56,4 +58,10 @@ public class Constants { public static final String HTTPS = "https://"; } + public static class Security { + + public static final long SECURITY_INFO_REFRESH_INTERVAL_MILLS = TimeUnit.SECONDS.toMillis(5); + + } + } diff --git a/client/src/main/java/com/alibaba/nacos/client/naming/NacosNamingMaintainService.java b/client/src/main/java/com/alibaba/nacos/client/naming/NacosNamingMaintainService.java index cbeb089de..c6f2a5de4 100644 --- a/client/src/main/java/com/alibaba/nacos/client/naming/NacosNamingMaintainService.java +++ b/client/src/main/java/com/alibaba/nacos/client/naming/NacosNamingMaintainService.java @@ -31,9 +31,16 @@ import com.alibaba.nacos.client.naming.remote.http.NamingHttpClientProxy; import com.alibaba.nacos.client.naming.utils.InitUtils; import com.alibaba.nacos.client.security.SecurityProxy; import com.alibaba.nacos.client.utils.ValidatorUtils; +import com.alibaba.nacos.common.utils.ThreadUtils; import java.util.Map; import java.util.Properties; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import static com.alibaba.nacos.client.constant.Constants.Security.SECURITY_INFO_REFRESH_INTERVAL_MILLS; +import static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER; /** * Nacos naming maintain service. @@ -48,6 +55,12 @@ public class NacosNamingMaintainService implements NamingMaintainService { private NamingHttpClientProxy serverProxy; + private ServerListManager serverListManager; + + private SecurityProxy securityProxy; + + private ScheduledExecutorService executorService; + public NacosNamingMaintainService(String serverList) throws NacosException { Properties properties = new Properties(); properties.setProperty(PropertyKeyConst.SERVER_ADDR, serverList); @@ -63,12 +76,26 @@ public class NacosNamingMaintainService implements NamingMaintainService { namespace = InitUtils.initNamespaceForNaming(properties); InitUtils.initSerialization(); InitUtils.initWebRootContext(properties); - ServerListManager serverListManager = new ServerListManager(properties, namespace); - SecurityProxy securityProxy = new SecurityProxy(properties, + serverListManager = new ServerListManager(properties, namespace); + securityProxy = new SecurityProxy(properties, NamingHttpClientManager.getInstance().getNacosRestTemplate()); + initSecurityProxy(); serverProxy = new NamingHttpClientProxy(namespace, securityProxy, serverListManager, properties, null); } + private void initSecurityProxy() { + this.executorService = new ScheduledThreadPoolExecutor(1, r -> { + Thread t = new Thread(r); + t.setName("com.alibaba.nacos.client.naming.maintainService.security"); + t.setDaemon(true); + return t; + }); + this.securityProxy.login(serverListManager.getServerList()); + this.executorService.scheduleWithFixedDelay(() -> securityProxy.login(serverListManager.getServerList()), 0, + SECURITY_INFO_REFRESH_INTERVAL_MILLS, TimeUnit.MILLISECONDS); + + } + @Override public void updateInstance(String serviceName, Instance instance) throws NacosException { updateInstance(serviceName, Constants.DEFAULT_GROUP, instance); @@ -167,6 +194,11 @@ public class NacosNamingMaintainService implements NamingMaintainService { @Override public void shutDown() throws NacosException { + String className = this.getClass().getName(); + NAMING_LOGGER.info("{} do shutdown begin", className); + serverListManager.shutdown(); serverProxy.shutdown(); + ThreadUtils.shutdownThreadPool(executorService, NAMING_LOGGER); + NAMING_LOGGER.info("{} do shutdown stop", className); } } diff --git a/client/src/main/java/com/alibaba/nacos/client/naming/cache/ServiceInfoHolder.java b/client/src/main/java/com/alibaba/nacos/client/naming/cache/ServiceInfoHolder.java index 03a89e34a..1dae55147 100644 --- a/client/src/main/java/com/alibaba/nacos/client/naming/cache/ServiceInfoHolder.java +++ b/client/src/main/java/com/alibaba/nacos/client/naming/cache/ServiceInfoHolder.java @@ -185,6 +185,7 @@ public class ServiceInfoHolder implements Closeable { if (oldService.getLastRefTime() > newService.getLastRefTime()) { NAMING_LOGGER.warn("out of date data received, old-t: {}, new-t: {}", oldService.getLastRefTime(), newService.getLastRefTime()); + return false; } boolean changed = false; Map oldHostMap = new HashMap(oldService.getHosts().size()); diff --git a/client/src/main/java/com/alibaba/nacos/client/naming/remote/NamingClientProxyDelegate.java b/client/src/main/java/com/alibaba/nacos/client/naming/remote/NamingClientProxyDelegate.java index bdff6c871..d2accbdb9 100644 --- a/client/src/main/java/com/alibaba/nacos/client/naming/remote/NamingClientProxyDelegate.java +++ b/client/src/main/java/com/alibaba/nacos/client/naming/remote/NamingClientProxyDelegate.java @@ -39,6 +39,7 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import static com.alibaba.nacos.client.constant.Constants.Security.SECURITY_INFO_REFRESH_INTERVAL_MILLS; import static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER; /** @@ -48,8 +49,6 @@ import static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER; */ public class NamingClientProxyDelegate implements NamingClientProxy { - private final long securityInfoRefreshIntervalMills = TimeUnit.SECONDS.toMillis(5); - private final ServerListManager serverListManager; private final ServiceInfoUpdateService serviceInfoUpdateService; @@ -87,7 +86,7 @@ public class NamingClientProxyDelegate implements NamingClientProxy { }); this.securityProxy.login(serverListManager.getServerList()); this.executorService.scheduleWithFixedDelay(() -> securityProxy.login(serverListManager.getServerList()), 0, - securityInfoRefreshIntervalMills, TimeUnit.MILLISECONDS); + SECURITY_INFO_REFRESH_INTERVAL_MILLS, TimeUnit.MILLISECONDS); } @Override diff --git a/client/src/test/java/com/alibaba/nacos/client/naming/NacosNamingMaintainServiceTest.java b/client/src/test/java/com/alibaba/nacos/client/naming/NacosNamingMaintainServiceTest.java index 300c3f643..c8ab19b9d 100644 --- a/client/src/test/java/com/alibaba/nacos/client/naming/NacosNamingMaintainServiceTest.java +++ b/client/src/test/java/com/alibaba/nacos/client/naming/NacosNamingMaintainServiceTest.java @@ -26,7 +26,9 @@ import com.alibaba.nacos.api.naming.pojo.Service; import com.alibaba.nacos.api.selector.AbstractSelector; import com.alibaba.nacos.api.selector.ExpressionSelector; import com.alibaba.nacos.api.selector.NoneSelector; +import com.alibaba.nacos.client.naming.core.ServerListManager; import com.alibaba.nacos.client.naming.remote.http.NamingHttpClientProxy; +import com.alibaba.nacos.client.security.SecurityProxy; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -37,6 +39,7 @@ import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; import java.util.Properties; +import java.util.concurrent.ScheduledExecutorService; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.mock; @@ -49,15 +52,35 @@ public class NacosNamingMaintainServiceTest { private NamingHttpClientProxy serverProxy; + private ServerListManager serverListManager; + + private SecurityProxy securityProxy; + + private ScheduledExecutorService executorService; + @Before public void setUp() throws Exception { Properties prop = new Properties(); prop.setProperty(PropertyKeyConst.NAMESPACE, "public"); nacosNamingMaintainService = new NacosNamingMaintainService(prop); + serverProxy = mock(NamingHttpClientProxy.class); + serverListManager = mock(ServerListManager.class); + securityProxy = mock(SecurityProxy.class); + executorService = mock(ScheduledExecutorService.class); + Field serverProxyField = NacosNamingMaintainService.class.getDeclaredField("serverProxy"); serverProxyField.setAccessible(true); serverProxyField.set(nacosNamingMaintainService, serverProxy); + Field serverListManagerField = NacosNamingMaintainService.class.getDeclaredField("serverListManager"); + serverListManagerField.setAccessible(true); + serverListManagerField.set(nacosNamingMaintainService, serverListManager); + Field securityProxyFiled = NacosNamingMaintainService.class.getDeclaredField("securityProxy"); + securityProxyFiled.setAccessible(true); + securityProxyFiled.set(nacosNamingMaintainService, securityProxy); + Field executorServiceField = NacosNamingMaintainService.class.getDeclaredField("executorService"); + executorServiceField.setAccessible(true); + executorServiceField.set(nacosNamingMaintainService, executorService); } @After @@ -275,8 +298,11 @@ public class NacosNamingMaintainServiceTest { @Test public void testShutDown() throws NacosException { + //when nacosNamingMaintainService.shutDown(); //then verify(serverProxy, times(1)).shutdown(); + verify(serverListManager, times(1)).shutdown(); + verify(executorService, times(1)).shutdown(); } } \ No newline at end of file diff --git a/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java b/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java index 0bc70f452..377ff55f5 100644 --- a/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java +++ b/common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java @@ -454,7 +454,9 @@ public abstract class RpcClient implements Closeable { LOGGER.info("Shutdown rpc client, set status to shutdown"); rpcClientStatus.set(RpcClientStatus.SHUTDOWN); LOGGER.info("Shutdown client event executor " + clientEventExecutor); - clientEventExecutor.shutdownNow(); + if (clientEventExecutor != null) { + clientEventExecutor.shutdownNow(); + } closeConnection(currentConnection); } diff --git a/common/src/test/java/com/alibaba/nacos/common/remote/client/RpcClientTest.java b/common/src/test/java/com/alibaba/nacos/common/remote/client/RpcClientTest.java index 0a209b346..680627617 100644 --- a/common/src/test/java/com/alibaba/nacos/common/remote/client/RpcClientTest.java +++ b/common/src/test/java/com/alibaba/nacos/common/remote/client/RpcClientTest.java @@ -389,4 +389,26 @@ public class RpcClientTest { Assert.assertNotNull(exception); Assert.assertEquals(RpcClientStatus.UNHEALTHY, rpcClient.rpcClientStatus.get()); } + + @Test + public void testRpcClientShutdownWhenClientDidntStart() throws NacosException { + RpcClient rpcClient = new RpcClient("test-client") { + @Override + public ConnectionType getConnectionType() { + return null; + } + + @Override + public int rpcPortOffset() { + return 0; + } + + @Override + public Connection connectToServer(ServerInfo serverInfo) throws Exception { + return null; + } + }; + + rpcClient.shutdown(); + } } \ No newline at end of file diff --git a/config/src/main/java/com/alibaba/nacos/config/server/utils/SimpleReadWriteLock.java b/config/src/main/java/com/alibaba/nacos/config/server/utils/SimpleReadWriteLock.java index bcaeb6116..795518293 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/utils/SimpleReadWriteLock.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/utils/SimpleReadWriteLock.java @@ -23,6 +23,12 @@ package com.alibaba.nacos.config.server.utils; */ public class SimpleReadWriteLock { + /** + * Zero means no lock; Negative Numbers mean write locks; Positive Numbers mean read locks, and the numeric value + * represents the number of read locks. + */ + private int status = 0; + /** * Try read lock. */ @@ -39,6 +45,10 @@ public class SimpleReadWriteLock { * Release the read lock. */ public synchronized void releaseReadLock() { + // when status equals 0, it should not decrement to negative numbers + if (status == 0) { + return; + } status--; } @@ -65,10 +75,5 @@ public class SimpleReadWriteLock { private boolean isFree() { return status == 0; } - - /** - * Zero means no lock; Negative Numbers mean write locks; Positive Numbers mean read locks, and the numeric value - * represents the number of read locks. - */ - private int status = 0; + } diff --git a/config/src/test/java/com/alibaba/nacos/config/server/service/capacity/CapacityServiceTest.java b/config/src/test/java/com/alibaba/nacos/config/server/service/capacity/CapacityServiceTest.java new file mode 100644 index 000000000..8190e4e01 --- /dev/null +++ b/config/src/test/java/com/alibaba/nacos/config/server/service/capacity/CapacityServiceTest.java @@ -0,0 +1,450 @@ +/* + * Copyright 1999-2018 Alibaba Group Holding Ltd. + * + * 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.nacos.config.server.service.capacity; + +import com.alibaba.nacos.config.server.constant.CounterMode; +import com.alibaba.nacos.config.server.model.capacity.Capacity; +import com.alibaba.nacos.config.server.model.capacity.GroupCapacity; +import com.alibaba.nacos.config.server.model.capacity.TenantCapacity; +import com.alibaba.nacos.config.server.service.repository.PersistService; +import com.alibaba.nacos.config.server.utils.PropertyUtil; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.springframework.mock.web.MockServletContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.util.ReflectionTestUtils; + +import java.util.ArrayList; +import java.util.List; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.when; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = MockServletContext.class) +@WebAppConfiguration +public class CapacityServiceTest { + + private CapacityService service; + + @Mock + private GroupCapacityPersistService groupCapacityPersistService; + + @Mock + private TenantCapacityPersistService tenantCapacityPersistService; + + @Mock + private PersistService persistService; + + @Before + public void setUp() { + service = new CapacityService(); + ReflectionTestUtils.setField(service, "groupCapacityPersistService", groupCapacityPersistService); + ReflectionTestUtils.setField(service, "tenantCapacityPersistService", tenantCapacityPersistService); + ReflectionTestUtils.setField(service, "persistService", persistService); + } + + @Test + public void testInit() { + service.init(); + } + + @Test + public void testCorrectUsage() { + List groupCapacityList = new ArrayList<>(); + GroupCapacity groupCapacity = new GroupCapacity(); + groupCapacity.setId(1L); + groupCapacity.setGroup("testGroup"); + groupCapacityList.add(groupCapacity); + when(groupCapacityPersistService.getCapacityList4CorrectUsage(0L, 100)).thenReturn(groupCapacityList); + when(groupCapacityPersistService.getCapacityList4CorrectUsage(1L, 100)).thenReturn(new ArrayList<>()); + when(groupCapacityPersistService.correctUsage(eq("testGroup"), any())).thenReturn(true); + + List tenantCapacityList = new ArrayList<>(); + TenantCapacity tenantCapacity = new TenantCapacity(); + tenantCapacity.setId(1L); + tenantCapacity.setTenant("testTenant"); + tenantCapacityList.add(tenantCapacity); + when(tenantCapacityPersistService.getCapacityList4CorrectUsage(0L, 100)).thenReturn(tenantCapacityList); + when(tenantCapacityPersistService.getCapacityList4CorrectUsage(1L, 100)).thenReturn(new ArrayList<>()); + when(tenantCapacityPersistService.correctUsage(eq("testTenant"), any())).thenReturn(true); + + service.correctUsage(); + + Mockito.verify(groupCapacityPersistService, times(1)).getCapacityList4CorrectUsage(0L, 100); + Mockito.verify(groupCapacityPersistService, times(1)).getCapacityList4CorrectUsage(1L, 100); + Mockito.verify(groupCapacityPersistService, times(1)).correctUsage(eq("testGroup"), any()); + + Mockito.verify(tenantCapacityPersistService, times(1)).getCapacityList4CorrectUsage(0L, 100); + Mockito.verify(tenantCapacityPersistService, times(1)).getCapacityList4CorrectUsage(1L, 100); + Mockito.verify(tenantCapacityPersistService, times(1)).correctUsage(eq("testTenant"), any()); + } + + @Test + public void testCorrectGroupUsage() { + when(groupCapacityPersistService.correctUsage(eq("testGroup"), any())).thenReturn(true); + service.correctGroupUsage("testGroup"); + Mockito.verify(groupCapacityPersistService, times(1)).correctUsage(eq("testGroup"), any()); + } + + @Test + public void testCorrectTenantUsage() { + when(tenantCapacityPersistService.correctUsage(eq("testTenant"), any())).thenReturn(true); + service.correctTenantUsage("testTenant"); + Mockito.verify(tenantCapacityPersistService, times(1)).correctUsage(eq("testTenant"), any()); + } + + @Test + public void testInitAllCapacity() { + List groupList = new ArrayList<>(); + groupList.add("testGroup"); + when(persistService.getGroupIdList(eq(1), eq(500))).thenReturn(groupList); + List tenantList = new ArrayList<>(); + tenantList.add("testTenant"); + when(persistService.getTenantIdList(eq(1), eq(500))).thenReturn(tenantList); + + GroupCapacity groupCapacity = new GroupCapacity(); + groupCapacity.setGroup("testGroup"); + groupCapacity.setUsage(300); + when(groupCapacityPersistService.insertGroupCapacity(any())).thenReturn(true); + when(groupCapacityPersistService.getGroupCapacity(eq("testGroup"))).thenReturn(groupCapacity); + when(groupCapacityPersistService.updateQuota(eq("testGroup"), eq(500))).thenReturn(true); + + TenantCapacity tenantCapacity = new TenantCapacity(); + tenantCapacity.setTenant("testTenant"); + tenantCapacity.setUsage(300); + when(tenantCapacityPersistService.insertTenantCapacity(any())).thenReturn(true); + when(tenantCapacityPersistService.getTenantCapacity(eq("testTenant"))).thenReturn(tenantCapacity); + when(tenantCapacityPersistService.updateQuota(eq("testTenant"), eq(500))).thenReturn(true); + + service.initAllCapacity(); + + Mockito.verify(groupCapacityPersistService, times(1)).insertGroupCapacity(any()); + Mockito.verify(groupCapacityPersistService, times(1)).getGroupCapacity(eq("testGroup")); + Mockito.verify(groupCapacityPersistService, times(1)).updateQuota(eq("testGroup"), eq(500)); + + Mockito.verify(tenantCapacityPersistService, times(1)).insertTenantCapacity(any()); + Mockito.verify(tenantCapacityPersistService, times(1)).getTenantCapacity(eq("testTenant")); + Mockito.verify(tenantCapacityPersistService, times(1)).updateQuota(eq("testTenant"), eq(500)); + } + + @Test + public void testInsertAndUpdateClusterUsage() { + when(groupCapacityPersistService.insertGroupCapacity(any())).thenReturn(true); + when(groupCapacityPersistService.incrementUsage(any())).thenReturn(true); + when(groupCapacityPersistService.incrementUsageWithDefaultQuotaLimit(any())).thenReturn(true); + when(groupCapacityPersistService.decrementUsage(any())).thenReturn(true); + + service.insertAndUpdateClusterUsage(CounterMode.INCREMENT, true); + Mockito.verify(groupCapacityPersistService, times(1)).incrementUsage(any()); + + service.insertAndUpdateClusterUsage(CounterMode.INCREMENT, false); + Mockito.verify(groupCapacityPersistService, times(1)).incrementUsageWithDefaultQuotaLimit(any()); + + service.insertAndUpdateClusterUsage(CounterMode.DECREMENT, true); + Mockito.verify(groupCapacityPersistService, times(1)).decrementUsage(any()); + + } + + @Test + public void testUpdateClusterUsage() { + when(groupCapacityPersistService.incrementUsageWithDefaultQuotaLimit(any())).thenReturn(true); + when(groupCapacityPersistService.decrementUsage(any())).thenReturn(true); + + service.updateClusterUsage(CounterMode.INCREMENT); + Mockito.verify(groupCapacityPersistService, times(1)).incrementUsageWithDefaultQuotaLimit(any()); + + service.updateClusterUsage(CounterMode.DECREMENT); + Mockito.verify(groupCapacityPersistService, times(1)).decrementUsage(any()); + } + + @Test + public void testInsertAndUpdateGroupUsage() { + GroupCapacity groupCapacity = new GroupCapacity(); + groupCapacity.setGroup("testGroup"); + groupCapacity.setUsage(300); + when(groupCapacityPersistService.getGroupCapacity("testGroup")).thenReturn(groupCapacity); + when(groupCapacityPersistService.incrementUsage(any())).thenReturn(true); + when(groupCapacityPersistService.incrementUsageWithDefaultQuotaLimit(any())).thenReturn(true); + when(groupCapacityPersistService.decrementUsage(any())).thenReturn(true); + + service.insertAndUpdateGroupUsage(CounterMode.INCREMENT, "testGroup", true); + Mockito.verify(groupCapacityPersistService, times(1)).incrementUsage(any()); + + service.insertAndUpdateClusterUsage(CounterMode.INCREMENT, false); + Mockito.verify(groupCapacityPersistService, times(1)).incrementUsageWithDefaultQuotaLimit(any()); + + service.insertAndUpdateClusterUsage(CounterMode.DECREMENT, true); + Mockito.verify(groupCapacityPersistService, times(1)).decrementUsage(any()); + + } + + @Test + public void testUpdateGroupUsage() { + when(groupCapacityPersistService.incrementUsageWithDefaultQuotaLimit(any())).thenReturn(true); + when(groupCapacityPersistService.decrementUsage(any())).thenReturn(true); + + service.updateGroupUsage(CounterMode.INCREMENT, "testGroup"); + Mockito.verify(groupCapacityPersistService, times(1)).incrementUsageWithDefaultQuotaLimit(any()); + + service.updateGroupUsage(CounterMode.DECREMENT, "testGroup"); + Mockito.verify(groupCapacityPersistService, times(1)).decrementUsage(any()); + } + + @Test + public void testGetGroupCapacity() { + GroupCapacity groupCapacity = new GroupCapacity(); + groupCapacity.setId(1L); + groupCapacity.setGroup("testGroup"); + when(groupCapacityPersistService.getGroupCapacity(eq("testGroup"))).thenReturn(groupCapacity); + + GroupCapacity resGroupCapacity = service.getGroupCapacity("testGroup"); + Assert.assertEquals(groupCapacity.getId(), resGroupCapacity.getId()); + Assert.assertEquals(groupCapacity.getGroup(), resGroupCapacity.getGroup()); + } + + @Test + public void testInitGroupCapacity() { + GroupCapacity groupCapacity = new GroupCapacity(); + groupCapacity.setGroup("testGroup"); + groupCapacity.setUsage(300); + when(groupCapacityPersistService.insertGroupCapacity(any())).thenReturn(true); + when(groupCapacityPersistService.getGroupCapacity(eq("testGroup"))).thenReturn(groupCapacity); + when(groupCapacityPersistService.updateQuota(eq("testGroup"), eq(500))).thenReturn(true); + + service.initGroupCapacity("testGroup"); + Mockito.verify(groupCapacityPersistService, times(1)).insertGroupCapacity(any()); + Mockito.verify(groupCapacityPersistService, times(1)).getGroupCapacity(eq("testGroup")); + Mockito.verify(groupCapacityPersistService, times(1)).updateQuota(eq("testGroup"), eq(500)); + } + + @Test + public void testGetCapacity() { + GroupCapacity groupCapacity = new GroupCapacity(); + groupCapacity.setId(1L); + when(groupCapacityPersistService.getGroupCapacity(eq("testGroup"))).thenReturn(groupCapacity); + + TenantCapacity tenantCapacity = new TenantCapacity(); + tenantCapacity.setId(2L); + when(tenantCapacityPersistService.getTenantCapacity(eq("testTenant"))).thenReturn(tenantCapacity); + + Capacity resCapacity1 = service.getCapacity("testGroup", null); + Assert.assertEquals(1L, resCapacity1.getId().longValue()); + + Capacity resCapacity2 = service.getCapacity(null, "testTenant"); + Assert.assertEquals(2L, resCapacity2.getId().longValue()); + } + + @Test + public void testGetCapacityWithDefault() { + TenantCapacity tenantCapacity = new TenantCapacity(); + tenantCapacity.setQuota(0); + tenantCapacity.setMaxSize(0); + tenantCapacity.setMaxAggrCount(0); + tenantCapacity.setMaxAggrSize(0); + when(tenantCapacityPersistService.getTenantCapacity(anyString())).thenReturn(tenantCapacity); + + GroupCapacity groupCapacity1 = new GroupCapacity(); + groupCapacity1.setQuota(0); + groupCapacity1.setMaxSize(0); + groupCapacity1.setMaxAggrCount(0); + groupCapacity1.setMaxAggrSize(0); + when(groupCapacityPersistService.getGroupCapacity(anyString())).thenReturn(groupCapacity1); + + //group is null + Capacity resCapacity1 = service.getCapacityWithDefault(null, "testTenant"); + Assert.assertEquals(PropertyUtil.getDefaultGroupQuota(), resCapacity1.getQuota().intValue()); + Assert.assertEquals(PropertyUtil.getDefaultMaxSize(), resCapacity1.getMaxSize().intValue()); + Assert.assertEquals(PropertyUtil.getDefaultMaxAggrCount(), resCapacity1.getMaxAggrCount().intValue()); + Assert.assertEquals(PropertyUtil.getDefaultMaxAggrSize(), resCapacity1.getMaxAggrSize().intValue()); + + //group is GroupCapacityPersistService.CLUSTER + Capacity resCapacity2 = service.getCapacityWithDefault(GroupCapacityPersistService.CLUSTER, null); + Assert.assertEquals(PropertyUtil.getDefaultClusterQuota(), resCapacity2.getQuota().intValue()); + Assert.assertEquals(PropertyUtil.getDefaultMaxSize(), resCapacity2.getMaxSize().intValue()); + Assert.assertEquals(PropertyUtil.getDefaultMaxAggrCount(), resCapacity2.getMaxAggrCount().intValue()); + Assert.assertEquals(PropertyUtil.getDefaultMaxAggrSize(), resCapacity2.getMaxAggrSize().intValue()); + + GroupCapacity groupCapacity2 = new GroupCapacity(); + groupCapacity2.setQuota(0); + groupCapacity2.setMaxSize(0); + groupCapacity2.setMaxAggrCount(0); + groupCapacity2.setMaxAggrSize(0); + when(groupCapacityPersistService.getGroupCapacity(anyString())).thenReturn(groupCapacity2); + + //tenant is null + Capacity resCapacity3 = service.getCapacityWithDefault("testGroup", null); + Assert.assertEquals(PropertyUtil.getDefaultGroupQuota(), resCapacity3.getQuota().intValue()); + Assert.assertEquals(PropertyUtil.getDefaultMaxSize(), resCapacity3.getMaxSize().intValue()); + Assert.assertEquals(PropertyUtil.getDefaultMaxAggrCount(), resCapacity3.getMaxAggrCount().intValue()); + Assert.assertEquals(PropertyUtil.getDefaultMaxAggrSize(), resCapacity3.getMaxAggrSize().intValue()); + } + + @Test + public void testInitCapacityV1() { + GroupCapacity groupCapacity = new GroupCapacity(); + groupCapacity.setUsage(300); + when(groupCapacityPersistService.getGroupCapacity(eq("testGroup"))).thenReturn(groupCapacity); + when(groupCapacityPersistService.insertGroupCapacity(any())).thenReturn(true); + when(groupCapacityPersistService.updateQuota(eq("testGroup"), eq(500))).thenReturn(true); + + TenantCapacity tenantCapacity = new TenantCapacity(); + tenantCapacity.setUsage(300); + when(tenantCapacityPersistService.getTenantCapacity(eq("testTenant"))).thenReturn(tenantCapacity); + when(tenantCapacityPersistService.insertTenantCapacity(any())).thenReturn(true); + when(tenantCapacityPersistService.updateQuota(eq("testTenant"), eq(500))).thenReturn(true); + + service.initCapacity("testGroup", null); + Mockito.verify(groupCapacityPersistService, times(1)).getGroupCapacity(eq("testGroup")); + Mockito.verify(groupCapacityPersistService, times(1)).insertGroupCapacity(any()); + Mockito.verify(groupCapacityPersistService, times(1)).updateQuota(eq("testGroup"), eq(500)); + + service.initCapacity(null, "testTenant"); + Mockito.verify(tenantCapacityPersistService, times(1)).getTenantCapacity(eq("testTenant")); + Mockito.verify(tenantCapacityPersistService, times(1)).insertTenantCapacity(any()); + Mockito.verify(tenantCapacityPersistService, times(1)).updateQuota(eq("testTenant"), eq(500)); + } + + @Test + public void testInitCapacityV2() { + when(groupCapacityPersistService.insertGroupCapacity(any())).thenReturn(true); + + service.initCapacity(GroupCapacityPersistService.CLUSTER, null); + Mockito.verify(groupCapacityPersistService, times(1)).insertGroupCapacity(any()); + } + + @Test + public void testInsertAndUpdateTenantUsage() { + TenantCapacity tenantCapacity = new TenantCapacity(); + tenantCapacity.setTenant("testTenant"); + tenantCapacity.setUsage(300); + when(tenantCapacityPersistService.getTenantCapacity(eq("testTenant"))).thenReturn(tenantCapacity); + when(tenantCapacityPersistService.incrementUsage(any())).thenReturn(true); + when(tenantCapacityPersistService.incrementUsageWithDefaultQuotaLimit(any())).thenReturn(true); + when(tenantCapacityPersistService.decrementUsage(any())).thenReturn(true); + + service.insertAndUpdateTenantUsage(CounterMode.INCREMENT, "testTenant", true); + Mockito.verify(tenantCapacityPersistService, times(1)).incrementUsage(any()); + + service.insertAndUpdateTenantUsage(CounterMode.INCREMENT, "testTenant", false); + Mockito.verify(tenantCapacityPersistService, times(1)).incrementUsageWithDefaultQuotaLimit(any()); + + service.insertAndUpdateTenantUsage(CounterMode.DECREMENT, "testTenant", true); + Mockito.verify(tenantCapacityPersistService, times(1)).decrementUsage(any()); + + } + + @Test + public void testUpdateTenantUsage() { + when(tenantCapacityPersistService.incrementUsageWithDefaultQuotaLimit(any())).thenReturn(true); + when(tenantCapacityPersistService.decrementUsage(any())).thenReturn(true); + + service.updateTenantUsage(CounterMode.INCREMENT, "testTenant"); + Mockito.verify(tenantCapacityPersistService, times(1)).incrementUsageWithDefaultQuotaLimit(any()); + + service.updateTenantUsage(CounterMode.DECREMENT, "testTenant"); + Mockito.verify(tenantCapacityPersistService, times(1)).decrementUsage(any()); + } + + @Test + public void testInitTenantCapacityV1() { + TenantCapacity tenantCapacity = new TenantCapacity(); + tenantCapacity.setTenant("testTenant"); + tenantCapacity.setUsage(300); + when(tenantCapacityPersistService.insertTenantCapacity(any())).thenReturn(true); + when(tenantCapacityPersistService.getTenantCapacity(eq("testTenant"))).thenReturn(tenantCapacity); + when(tenantCapacityPersistService.updateQuota(eq("testTenant"), eq(500))).thenReturn(true); + + service.initTenantCapacity("testTenant"); + Mockito.verify(tenantCapacityPersistService, times(1)).insertTenantCapacity(any()); + Mockito.verify(tenantCapacityPersistService, times(1)).getTenantCapacity(eq("testTenant")); + Mockito.verify(tenantCapacityPersistService, times(1)).updateQuota(eq("testTenant"), eq(500)); + } + + @Test + public void testInitTenantCapacityV2() { + TenantCapacity tenantCapacity = new TenantCapacity(); + tenantCapacity.setTenant("testTenant"); + tenantCapacity.setUsage(300); + when(tenantCapacityPersistService.insertTenantCapacity(any())).thenReturn(true); + + service.initTenantCapacity("testTenant", 0, 0, 0, 0); + Mockito.verify(tenantCapacityPersistService, times(1)).insertTenantCapacity(any()); + } + + @Test + public void testGetTenantCapacity() { + TenantCapacity tenantCapacity = new TenantCapacity(); + tenantCapacity.setId(1L); + tenantCapacity.setTenant("testTenant"); + when(tenantCapacityPersistService.getTenantCapacity(eq("testTenant"))).thenReturn(tenantCapacity); + + TenantCapacity resTenantCapacity = service.getTenantCapacity("testTenant"); + Assert.assertEquals(tenantCapacity.getId(), resTenantCapacity.getId()); + Assert.assertEquals(tenantCapacity.getTenant(), resTenantCapacity.getTenant()); + } + + @Test + public void testInsertOrUpdateCapacityV1() { + //tenant is null + GroupCapacity groupCapacity = new GroupCapacity(); + groupCapacity.setUsage(300); + when(groupCapacityPersistService.getGroupCapacity(eq("testGroup"))).thenReturn(groupCapacity); + when(groupCapacityPersistService.updateGroupCapacity(eq("testGroup"), eq(0), eq(0), eq(0), eq(0))) + .thenReturn(true); + service.insertOrUpdateCapacity("testGroup", null, 0, 0, 0, 0); + Mockito.verify(groupCapacityPersistService, times(1)).getGroupCapacity(eq("testGroup")); + Mockito.verify(groupCapacityPersistService, times(1)) + .updateGroupCapacity(eq("testGroup"), eq(0), eq(0), eq(0), eq(0)); + + //tenant is not null + TenantCapacity tenantCapacity = new TenantCapacity(); + tenantCapacity.setTenant("testTenant"); + when(tenantCapacityPersistService.getTenantCapacity(eq("testTenant"))).thenReturn(tenantCapacity); + when(tenantCapacityPersistService.updateTenantCapacity(eq("testTenant"), eq(0), eq(0), eq(0), eq(0))) + .thenReturn(true); + service.insertOrUpdateCapacity(null, "testTenant", 0, 0, 0, 0); + Mockito.verify(tenantCapacityPersistService, times(1)).getTenantCapacity(eq("testTenant")); + Mockito.verify(tenantCapacityPersistService, times(1)) + .updateTenantCapacity(eq("testTenant"), eq(0), eq(0), eq(0), eq(0)); + } + + @Test + public void testInsertOrUpdateCapacityV2() { + when(groupCapacityPersistService.getGroupCapacity(eq("testGroup"))).thenReturn(null); + when(groupCapacityPersistService.insertGroupCapacity(any())).thenReturn(true); + service.insertOrUpdateCapacity("testGroup", null, 0, 0, 0, 0); + Mockito.verify(groupCapacityPersistService, times(1)).getGroupCapacity(eq("testGroup")); + Mockito.verify(groupCapacityPersistService, times(1)).insertGroupCapacity(any()); + + when(tenantCapacityPersistService.getTenantCapacity(eq("testTenant"))).thenReturn(null); + when(tenantCapacityPersistService.insertTenantCapacity(any())).thenReturn(true); + service.insertOrUpdateCapacity(null, "testTenant", 0, 0, 0, 0); + Mockito.verify(tenantCapacityPersistService, times(1)).getTenantCapacity(eq("testTenant")); + Mockito.verify(tenantCapacityPersistService, times(1)).insertTenantCapacity(any()); + } + +} \ No newline at end of file diff --git a/config/src/test/java/com/alibaba/nacos/config/server/utils/RegexParserTest.java b/config/src/test/java/com/alibaba/nacos/config/server/utils/RegexParserTest.java new file mode 100644 index 000000000..bc537c09b --- /dev/null +++ b/config/src/test/java/com/alibaba/nacos/config/server/utils/RegexParserTest.java @@ -0,0 +1,42 @@ +/* + * Copyright 1999-2018 Alibaba Group Holding Ltd. + * + * 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.nacos.config.server.utils; + +import org.junit.Assert; +import org.junit.Test; + +public class RegexParserTest { + + @Test + public void testRegexFormat() { + try { + RegexParser.regexFormat(null); + Assert.fail(); + } catch (NullPointerException e) { + System.out.println(e.toString()); + } + + Assert.assertEquals("^test.*\\!.{1}xxxx$", RegexParser.regexFormat("test*!?xxxx")); + } + + @Test + public void testContainsWildcard() { + Assert.assertFalse(RegexParser.containsWildcard("test")); + Assert.assertTrue(RegexParser.containsWildcard("?")); + Assert.assertTrue(RegexParser.containsWildcard("*")); + } +} diff --git a/config/src/test/java/com/alibaba/nacos/config/server/utils/RequestUtilTest.java b/config/src/test/java/com/alibaba/nacos/config/server/utils/RequestUtilTest.java index e1641cc90..cf5324f32 100644 --- a/config/src/test/java/com/alibaba/nacos/config/server/utils/RequestUtilTest.java +++ b/config/src/test/java/com/alibaba/nacos/config/server/utils/RequestUtilTest.java @@ -16,11 +16,14 @@ package com.alibaba.nacos.config.server.utils; +import com.alibaba.nacos.api.common.Constants; +import com.alibaba.nacos.auth.model.User; import org.junit.Assert; import org.junit.Test; import org.mockito.Mockito; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; import static org.mockito.ArgumentMatchers.eq; @@ -31,32 +34,65 @@ public class RequestUtilTest { private static final String X_FORWARDED_FOR = "X-Forwarded-For"; @Test - public void getRemoteIp() { + public void testGetRemoteIp() { HttpServletRequest request = Mockito.mock(HttpServletRequest.class); Mockito.when(request.getRemoteAddr()).thenReturn("127.0.0.1"); - Assert.assertEquals(RequestUtil.getRemoteIp(request), "127.0.0.1"); + Assert.assertEquals("127.0.0.1", RequestUtil.getRemoteIp(request)); Mockito.when(request.getHeader(eq(X_REAL_IP))).thenReturn("127.0.0.2"); - Assert.assertEquals(RequestUtil.getRemoteIp(request), "127.0.0.2"); + Assert.assertEquals("127.0.0.2", RequestUtil.getRemoteIp(request)); Mockito.when(request.getHeader(eq(X_FORWARDED_FOR))).thenReturn("127.0.0.3"); - Assert.assertEquals(RequestUtil.getRemoteIp(request), "127.0.0.3"); + Assert.assertEquals("127.0.0.3", RequestUtil.getRemoteIp(request)); Mockito.when(request.getHeader(eq(X_FORWARDED_FOR))).thenReturn("127.0.0.3, 127.0.0.4"); - Assert.assertEquals(RequestUtil.getRemoteIp(request), "127.0.0.3"); + Assert.assertEquals("127.0.0.3", RequestUtil.getRemoteIp(request)); Mockito.when(request.getHeader(eq(X_FORWARDED_FOR))).thenReturn(""); - Assert.assertEquals(RequestUtil.getRemoteIp(request), "127.0.0.2"); + Assert.assertEquals("127.0.0.2", RequestUtil.getRemoteIp(request)); Mockito.when(request.getHeader(eq(X_REAL_IP))).thenReturn(""); - Assert.assertEquals(RequestUtil.getRemoteIp(request), "127.0.0.1"); + Assert.assertEquals("127.0.0.1", RequestUtil.getRemoteIp(request)); } @Test - public void getAppName() { + public void testGetAppName() { HttpServletRequest request = Mockito.mock(HttpServletRequest.class); Mockito.when(request.getHeader(eq(RequestUtil.CLIENT_APPNAME_HEADER))).thenReturn("test"); - Assert.assertEquals(RequestUtil.getAppName(request), "test"); + Assert.assertEquals("test", RequestUtil.getAppName(request)); } + + @Test + public void testGetUser() { + HttpServletRequest request = Mockito.mock(HttpServletRequest.class); + HttpSession session = Mockito.mock(HttpSession.class); + User user = new User(); + user.setUserName("test"); + Mockito.when(request.getSession()).thenReturn(session); + Mockito.when(session.getAttribute(eq(RequestUtil.NACOS_USER_KEY))).thenReturn(user); + Assert.assertEquals("test", RequestUtil.getUser(request).getUserName()); + } + + @Test + public void testGetSrcUserNameV1() { + HttpServletRequest request = Mockito.mock(HttpServletRequest.class); + HttpSession session = Mockito.mock(HttpSession.class); + User user = new User(); + user.setUserName("test"); + Mockito.when(request.getSession()).thenReturn(session); + Mockito.when(session.getAttribute(eq(RequestUtil.NACOS_USER_KEY))).thenReturn(user); + Assert.assertEquals("test", RequestUtil.getSrcUserName(request)); + } + + @Test + public void testGetSrcUserNameV2() { + HttpServletRequest request = Mockito.mock(HttpServletRequest.class); + HttpSession session = Mockito.mock(HttpSession.class); + Mockito.when(request.getSession()).thenReturn(session); + Mockito.when(session.getAttribute(eq(RequestUtil.NACOS_USER_KEY))).thenReturn(null); + Mockito.when(request.getParameter(eq(Constants.USERNAME))).thenReturn("parameterName"); + Assert.assertEquals("parameterName", RequestUtil.getSrcUserName(request)); + } + } diff --git a/config/src/test/java/com/alibaba/nacos/config/server/utils/ResponseUtilTest.java b/config/src/test/java/com/alibaba/nacos/config/server/utils/ResponseUtilTest.java new file mode 100644 index 000000000..0d00d62b3 --- /dev/null +++ b/config/src/test/java/com/alibaba/nacos/config/server/utils/ResponseUtilTest.java @@ -0,0 +1,38 @@ +/* + * Copyright 1999-2018 Alibaba Group Holding Ltd. + * + * 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.nacos.config.server.utils; + +import org.junit.Assert; +import org.junit.Test; +import org.springframework.mock.web.MockHttpServletResponse; + +import java.io.UnsupportedEncodingException; + +public class ResponseUtilTest { + + @Test + public void testWriteErrMsg() { + MockHttpServletResponse response = new MockHttpServletResponse(); + ResponseUtil.writeErrMsg(response, 404, "test"); + Assert.assertEquals(404, response.getStatus()); + try { + Assert.assertEquals("test\r\n", response.getContentAsString()); + } catch (UnsupportedEncodingException e) { + System.out.println(e.toString()); + } + } +} diff --git a/config/src/test/java/com/alibaba/nacos/config/server/utils/SimpleReadWriteLockTest.java b/config/src/test/java/com/alibaba/nacos/config/server/utils/SimpleReadWriteLockTest.java index c2d6a3021..c6ed47423 100644 --- a/config/src/test/java/com/alibaba/nacos/config/server/utils/SimpleReadWriteLockTest.java +++ b/config/src/test/java/com/alibaba/nacos/config/server/utils/SimpleReadWriteLockTest.java @@ -19,13 +19,11 @@ package com.alibaba.nacos.config.server.utils; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.web.WebAppConfiguration; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @RunWith(SpringJUnit4ClassRunner.class) -@WebAppConfiguration public class SimpleReadWriteLockTest { @Test @@ -63,6 +61,14 @@ public class SimpleReadWriteLockTest { assertFalse(lock.tryWriteLock()); } + @Test + public void testFirstWriteLockThenReadLock() { + SimpleReadWriteLock lock = new SimpleReadWriteLock(); + + assertTrue(lock.tryWriteLock()); + assertFalse(lock.tryReadLock()); + } + @Test public void testDoubleReadLockAndOneReleaseOneFailed() { SimpleReadWriteLock lock = new SimpleReadWriteLock(); diff --git a/pom.xml b/pom.xml index 6a64b5934..7d7b3c4d3 100644 --- a/pom.xml +++ b/pom.xml @@ -137,7 +137,7 @@ 1.2 1.7.7 1.2.3 - 2.15.0 + 2.16.0 4.1.3 8.0.21