Support jdk17 (#3339)

Adjust the test logic, use jdk17 to build, 8, 11, 17 to run
This commit is contained in:
Robert Lu 2024-02-20 04:58:52 -06:00 committed by GitHub
parent 2b7a989e29
commit 8fef1b5eee
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
34 changed files with 1206 additions and 1111 deletions

View File

@ -1,16 +1,5 @@
version: 2
jobs:
integration-test:
docker:
- image: cimg/openjdk:8.0
working_directory: ~/sentinel
environment:
MAVEN_OPTS: -Xmx3200m
steps:
- checkout
# Run tests
- run: mvn integration-test
document-lint:
docker:
# this image is build from Dockerfile
@ -49,5 +38,4 @@ workflows:
version: 2
ci:
jobs:
- integration-test
- document-lint

View File

@ -3,9 +3,7 @@ name: Sentinel CI
on:
push:
branches:
- master
- "1.8"
- "2.0"
- '*'
pull_request:
branches:
- master
@ -17,20 +15,26 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
java: [8, 11]
java: [8, 11, 17]
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Setup Java
uses: actions/setup-java@v3
- name: Setup Java for test
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java }}
distribution: 'temurin'
architecture: x64
cache: 'maven'
- name: Setup Java for mvn
uses: actions/setup-java@v4
with:
java-version: 17
distribution: 'temurin'
- name: Test with Maven
run: mvn --batch-mode test
run: mvn --batch-mode test -Dsurefire.jdk-toolchain-version=${{ matrix.java }}
- name: Build with Maven
run: mvn install -DskipTests=true -Dmaven.javadoc.skip=true -B -V -DminimumPriority=1

View File

@ -34,7 +34,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
@ -48,6 +48,11 @@ jobs:
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
- name: Setup Java
uses: actions/setup-java@v4
with:
java-version: 17
distribution: 'temurin'
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
# If this step fails, then you should remove it and run the build manually (see below)

74
pom.xml
View File

@ -46,7 +46,7 @@
<!-- Test libs -->
<junit.version>4.12</junit.version>
<mockito.version>2.28.2</mockito.version>
<mockito.version>3.12.4</mockito.version>
<assertj.version>3.12.1</assertj.version>
<awaitility.version>3.1.5</awaitility.version>
<powermock.version>2.0.0</powermock.version>
@ -56,14 +56,14 @@
<java.source.version>1.8</java.source.version>
<java.target.version>1.8</java.target.version>
<java.encoding>UTF-8</java.encoding>
<maven.compiler.version>3.8.0</maven.compiler.version>
<maven.surefire.version>2.22.1</maven.surefire.version>
<maven.compiler.version>3.12.0</maven.compiler.version>
<maven.surefire.version>3.2.5</maven.surefire.version>
<maven.source.version>3.0.1</maven.source.version>
<maven.javadoc.version>3.0.1</maven.javadoc.version>
<maven.deploy.version>2.8.2</maven.deploy.version>
<maven.gpg.version>1.6</maven.gpg.version>
<maven.jacoco.version>0.8.3</maven.jacoco.version>
<maven.jar.version>3.1.0</maven.jar.version>
<maven.jar.version>3.3.0</maven.jar.version>
<maven.pmd.version>3.8</maven.pmd.version>
</properties>
@ -189,6 +189,12 @@
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
@ -207,18 +213,6 @@
<version>2.0.0.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
@ -271,15 +265,33 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.version}</version>
<executions>
<execution>
<id>default-compile</id>
<configuration>
<release>17</release>
</configuration>
</execution>
<execution>
<id>base-compile</id>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<excludes>
<exclude>module-info.java</exclude>
</excludes>
</configuration>
</execution>
</executions>
<configuration>
<source>${java.source.version}</source>
<target>${java.target.version}</target>
<encoding>${java.encoding}</encoding>
<release>8</release>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven.surefire.version}</version>
<configuration>
<!-- CircleCI build workaround -->
<argLine>@{argLine} -Xms1024m -Xmx2048m</argLine>
@ -394,6 +406,30 @@
</repository>
</distributionManagement>
</profile>
<profile>
<id>custom-test-runtime-version</id>
<activation>
<property>
<name>surefire.jdk-toolchain-version</name>
</property>
</activation>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven.surefire.version}</version>
<configuration>
<jdkToolchain>
<version>${surefire.jdk-toolchain-version}</version>
</jdkToolchain>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</profile>
</profiles>
</project>

View File

@ -43,7 +43,7 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.2.6.RELEASE</version>
<version>2.4.13</version>
<scope>test</scope>
</dependency>
<dependency>
@ -66,7 +66,7 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<forkMode>always</forkMode>
<reuseForks>false</reuseForks>
</configuration>
</plugin>
</plugins>

View File

@ -14,6 +14,7 @@
<properties>
<servlet.api.version>3.1.0</servlet.api.version>
<spring.boot.version>2.4.13</spring.boot.version>
</properties>
<dependencies>
@ -37,13 +38,13 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>1.5.17.RELEASE</version>
<version>${spring.boot.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>1.5.17.RELEASE</version>
<version>${spring.boot.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

View File

@ -41,16 +41,6 @@
<artifactId>sentinel-datasource-nacos</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
@ -58,7 +48,7 @@
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<artifactId>mockito-inline</artifactId>
<scope>test</scope>
</dependency>
<dependency>

View File

@ -0,0 +1,57 @@
/*
* 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.csp.sentinel.cluster;
import com.alibaba.csp.sentinel.util.TimeUtil;
import org.junit.runner.RunWith;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
/**
* Mock support for {@link TimeUtil}
*
* @author jason
*/
@RunWith(MockitoJUnitRunner.class)
public abstract class AbstractTimeBasedTest {
private long currentMillis = 0;
public MockedStatic<TimeUtil> mockTimeUtil() {
MockedStatic<TimeUtil> mocked = Mockito.mockStatic(TimeUtil.class);
mocked.when(TimeUtil::currentTimeMillis).thenReturn(currentMillis);
return mocked;
}
protected final void useActualTime(MockedStatic<TimeUtil> mocked) {
mocked.when(TimeUtil::currentTimeMillis).thenCallRealMethod();
}
protected final void setCurrentMillis(MockedStatic<TimeUtil> mocked, long cur) {
currentMillis = cur;
mocked.when(TimeUtil::currentTimeMillis).thenReturn(currentMillis);
}
protected final void sleep(MockedStatic<TimeUtil> mocked, long t) {
currentMillis += t;
mocked.when(TimeUtil::currentTimeMillis).thenReturn(currentMillis);
}
protected final void sleepSecond(MockedStatic<TimeUtil> mocked, long timeSec) {
sleep(mocked, timeSec * 1000);
}
}

View File

@ -21,14 +21,16 @@ import com.alibaba.csp.sentinel.cluster.flow.rule.ClusterFlowRuleManager;
import com.alibaba.csp.sentinel.cluster.flow.statistic.concurrent.CurrentConcurrencyManager;
import com.alibaba.csp.sentinel.cluster.flow.statistic.concurrent.TokenCacheNodeManager;
import com.alibaba.csp.sentinel.cluster.server.connection.ConnectionManager;
import com.alibaba.csp.sentinel.cluster.server.AbstractTimeBasedTest;
import com.alibaba.csp.sentinel.slots.block.ClusterRuleConstant;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.ClusterFlowConfig;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.test.AbstractTimeBasedTest;
import com.alibaba.csp.sentinel.util.TimeUtil;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.MockedStatic;
import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
@ -60,56 +62,60 @@ public class ConcurrentClusterFlowCheckerTest extends AbstractTimeBasedTest {
@Test
public void testEasyAcquireAndRelease() throws InterruptedException {
setCurrentMillis(System.currentTimeMillis());
FlowRule rule = ClusterFlowRuleManager.getFlowRuleById(111L);
ArrayList<Long> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
TokenResult result = ConcurrentClusterFlowChecker.acquireConcurrentToken("127.0.0.1", rule, 1);
Assert.assertTrue("fail to acquire token",
result.getStatus() == TokenResultStatus.OK && result.getTokenId() != 0);
list.add(result.getTokenId());
}
for (int i = 0; i < 10; i++) {
TokenResult result = ConcurrentClusterFlowChecker.acquireConcurrentToken("127.0.0.1", rule, 1);
Assert.assertTrue("fail to acquire block token",
result.getStatus() == TokenResultStatus.BLOCKED);
}
for (int i = 0; i < 10; i++) {
TokenResult result = ConcurrentClusterFlowChecker.releaseConcurrentToken(list.get(i));
try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
setCurrentMillis(mocked, System.currentTimeMillis());
FlowRule rule = ClusterFlowRuleManager.getFlowRuleById(111L);
ArrayList<Long> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
TokenResult result = ConcurrentClusterFlowChecker.acquireConcurrentToken("127.0.0.1", rule, 1);
Assert.assertTrue("fail to acquire token",
result.getStatus() == TokenResultStatus.OK && result.getTokenId() != 0);
list.add(result.getTokenId());
}
for (int i = 0; i < 10; i++) {
TokenResult result = ConcurrentClusterFlowChecker.acquireConcurrentToken("127.0.0.1", rule, 1);
Assert.assertTrue("fail to acquire block token",
result.getStatus() == TokenResultStatus.BLOCKED);
}
for (int i = 0; i < 10; i++) {
TokenResult result = ConcurrentClusterFlowChecker.releaseConcurrentToken(list.get(i));
Assert.assertTrue("fail to release token",
result.getStatus() == TokenResultStatus.RELEASE_OK);
}
Assert.assertTrue("fail to release token",
result.getStatus() == TokenResultStatus.RELEASE_OK);
CurrentConcurrencyManager.get(111L).get() == 0 && TokenCacheNodeManager.getSize() == 0);
}
Assert.assertTrue("fail to release token",
CurrentConcurrencyManager.get(111L).get() == 0 && TokenCacheNodeManager.getSize() == 0);
}
@Test
public void testConcurrentAcquireAndRelease() throws InterruptedException {
setCurrentMillis(System.currentTimeMillis());
final FlowRule rule = ClusterFlowRuleManager.getFlowRuleById(111L);
final CountDownLatch countDownLatch = new CountDownLatch(1000);
ExecutorService pool = Executors.newFixedThreadPool(100);
try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
setCurrentMillis(mocked, System.currentTimeMillis());
final FlowRule rule = ClusterFlowRuleManager.getFlowRuleById(111L);
final CountDownLatch countDownLatch = new CountDownLatch(1000);
ExecutorService pool = Executors.newFixedThreadPool(100);
for (long i = 0; i < 1000; i++) {
Runnable task = new Runnable() {
@Override
public void run() {
assert rule != null;
TokenResult result = ConcurrentClusterFlowChecker.acquireConcurrentToken("127.0.0.1", rule, 1);
Assert.assertTrue("concurrent control fail", CurrentConcurrencyManager.get(111L).get() <= rule.getCount());
if (result.getStatus() == TokenResultStatus.OK) {
ConcurrentClusterFlowChecker.releaseConcurrentToken(result.getTokenId());
for (long i = 0; i < 1000; i++) {
Runnable task = new Runnable() {
@Override
public void run() {
assert rule != null;
TokenResult result = ConcurrentClusterFlowChecker.acquireConcurrentToken("127.0.0.1", rule, 1);
Assert.assertTrue("concurrent control fail", CurrentConcurrencyManager.get(111L).get() <= rule.getCount());
if (result.getStatus() == TokenResultStatus.OK) {
ConcurrentClusterFlowChecker.releaseConcurrentToken(result.getTokenId());
}
countDownLatch.countDown();
}
countDownLatch.countDown();
}
};
pool.execute(task);
};
pool.execute(task);
}
countDownLatch.await();
pool.shutdown();
assert rule != null;
Assert.assertTrue("fail to acquire and release token",
CurrentConcurrencyManager.get(rule.getClusterConfig().getFlowId()).get() == 0 && TokenCacheNodeManager.getSize() == 0);
}
countDownLatch.await();
pool.shutdown();
assert rule != null;
Assert.assertTrue("fail to acquire and release token",
CurrentConcurrencyManager.get(rule.getClusterConfig().getFlowId()).get() == 0 && TokenCacheNodeManager.getSize() == 0);
}
@Test

View File

@ -16,16 +16,16 @@
package com.alibaba.csp.sentinel.cluster.flow.statistic.concurrent;
import com.alibaba.csp.sentinel.cluster.flow.rule.ClusterFlowRuleManager;
import com.alibaba.csp.sentinel.cluster.flow.statistic.concurrent.TokenCacheNode;
import com.alibaba.csp.sentinel.cluster.flow.statistic.concurrent.TokenCacheNodeManager;
import com.alibaba.csp.sentinel.cluster.server.AbstractTimeBasedTest;
import com.alibaba.csp.sentinel.slots.block.ClusterRuleConstant;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.ClusterFlowConfig;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.test.AbstractTimeBasedTest;
import com.alibaba.csp.sentinel.util.TimeUtil;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.MockedStatic;
import java.util.ArrayList;
import java.util.List;
@ -52,28 +52,30 @@ public class TokenCacheNodeManagerTest extends AbstractTimeBasedTest {
@Test
public void testPutTokenCacheNode() throws InterruptedException {
setCurrentMillis(System.currentTimeMillis());
try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
setCurrentMillis(mocked, System.currentTimeMillis());
for (long i = 0; i < 100; i++) {
final TokenCacheNode node = new TokenCacheNode();
node.setTokenId(i);
node.setFlowId(111L);
node.setResourceTimeout(10000L);
node.setClientTimeout(10000L);
node.setClientAddress("localhost");
if (TokenCacheNodeManager.validToken(node)) {
TokenCacheNodeManager.putTokenCacheNode(node.getTokenId(), node);
for (long i = 0; i < 100; i++) {
final TokenCacheNode node = new TokenCacheNode();
node.setTokenId(i);
node.setFlowId(111L);
node.setResourceTimeout(10000L);
node.setClientTimeout(10000L);
node.setClientAddress("localhost");
if (TokenCacheNodeManager.validToken(node)) {
TokenCacheNodeManager.putTokenCacheNode(node.getTokenId(), node);
}
}
Assert.assertEquals(100, TokenCacheNodeManager.getSize());
for (int i = 0; i < 100; i++) {
TokenCacheNodeManager.getTokenCacheNode((long) (Math.random() * 100));
}
List<Long> keyList = new ArrayList<>(TokenCacheNodeManager.getCacheKeySet());
for (int i = 0; i < 100; i++) {
Assert.assertEquals(i, (long) keyList.get(i));
TokenCacheNodeManager.removeTokenCacheNode(i);
}
}
Assert.assertEquals(100, TokenCacheNodeManager.getSize());
for (int i = 0; i < 100; i++) {
TokenCacheNodeManager.getTokenCacheNode((long) (Math.random() * 100));
}
List<Long> keyList = new ArrayList<>(TokenCacheNodeManager.getCacheKeySet());
for (int i = 0; i < 100; i++) {
Assert.assertEquals(i, (long) keyList.get(i));
TokenCacheNodeManager.removeTokenCacheNode(i);
}
}
}

View File

@ -16,10 +16,12 @@
package com.alibaba.csp.sentinel.cluster.flow.statistic.limit;
import com.alibaba.csp.sentinel.cluster.server.config.ClusterServerConfigManager;
import com.alibaba.csp.sentinel.cluster.test.AbstractTimeBasedTest;
import com.alibaba.csp.sentinel.cluster.server.AbstractTimeBasedTest;
import com.alibaba.csp.sentinel.util.TimeUtil;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.MockedStatic;
public class GlobalRequestLimiterTest extends AbstractTimeBasedTest {
@Before
@ -29,21 +31,23 @@ public class GlobalRequestLimiterTest extends AbstractTimeBasedTest {
@Test
public void testPass() throws InterruptedException {
setCurrentMillis(System.currentTimeMillis());
GlobalRequestLimiter.initIfAbsent("user");
Assert.assertNotNull(GlobalRequestLimiter.getRequestLimiter("user"));
Assert.assertEquals(3, GlobalRequestLimiter.getMaxAllowedQps("user"), 0.01);
Assert.assertTrue(GlobalRequestLimiter.tryPass("user"));
Assert.assertTrue(GlobalRequestLimiter.tryPass("user"));
Assert.assertTrue(GlobalRequestLimiter.tryPass("user"));
Assert.assertFalse(GlobalRequestLimiter.tryPass("user"));
Assert.assertEquals(3, GlobalRequestLimiter.getCurrentQps("user"), 0.01);
try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
setCurrentMillis(mocked, System.currentTimeMillis());
GlobalRequestLimiter.initIfAbsent("user");
Assert.assertNotNull(GlobalRequestLimiter.getRequestLimiter("user"));
Assert.assertEquals(3, GlobalRequestLimiter.getMaxAllowedQps("user"), 0.01);
Assert.assertTrue(GlobalRequestLimiter.tryPass("user"));
Assert.assertTrue(GlobalRequestLimiter.tryPass("user"));
Assert.assertTrue(GlobalRequestLimiter.tryPass("user"));
Assert.assertFalse(GlobalRequestLimiter.tryPass("user"));
Assert.assertEquals(3, GlobalRequestLimiter.getCurrentQps("user"), 0.01);
// wait a second to refresh the window
sleep(1000);
Assert.assertTrue(GlobalRequestLimiter.tryPass("user"));
Assert.assertTrue(GlobalRequestLimiter.tryPass("user"));
Assert.assertEquals(2, GlobalRequestLimiter.getCurrentQps("user"), 0.01);
// wait a second to refresh the window
sleep(mocked, 1000);
Assert.assertTrue(GlobalRequestLimiter.tryPass("user"));
Assert.assertTrue(GlobalRequestLimiter.tryPass("user"));
Assert.assertEquals(2, GlobalRequestLimiter.getCurrentQps("user"), 0.01);
}
}
@Test

View File

@ -15,8 +15,10 @@
*/
package com.alibaba.csp.sentinel.cluster.flow.statistic.limit;
import com.alibaba.csp.sentinel.cluster.test.AbstractTimeBasedTest;
import com.alibaba.csp.sentinel.cluster.server.AbstractTimeBasedTest;
import com.alibaba.csp.sentinel.util.TimeUtil;
import org.junit.Test;
import org.mockito.MockedStatic;
import static org.junit.Assert.*;
@ -24,21 +26,23 @@ public class RequestLimiterTest extends AbstractTimeBasedTest {
@Test
public void testRequestLimiter() {
setCurrentMillis(System.currentTimeMillis());
RequestLimiter limiter = new RequestLimiter(10);
limiter.add(3);
limiter.add(3);
limiter.add(3);
assertTrue(limiter.canPass());
assertEquals(9, limiter.getSum());
limiter.add(3);
assertFalse(limiter.canPass());
try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
setCurrentMillis(mocked, System.currentTimeMillis());
RequestLimiter limiter = new RequestLimiter(10);
limiter.add(3);
limiter.add(3);
limiter.add(3);
assertTrue(limiter.canPass());
assertEquals(9, limiter.getSum());
limiter.add(3);
assertFalse(limiter.canPass());
// wait a second to refresh the window
sleep(1000);
limiter.add(3);
assertTrue(limiter.tryPass());
assertTrue(limiter.canPass());
assertEquals(4, limiter.getSum());
// wait a second to refresh the window
sleep(mocked, 1000);
limiter.add(3);
assertTrue(limiter.tryPass());
assertTrue(limiter.canPass());
assertEquals(4, limiter.getSum());
}
}
}

View File

@ -16,31 +16,35 @@
package com.alibaba.csp.sentinel.cluster.flow.statistic.metric;
import com.alibaba.csp.sentinel.cluster.flow.statistic.data.ClusterFlowEvent;
import com.alibaba.csp.sentinel.cluster.test.AbstractTimeBasedTest;
import com.alibaba.csp.sentinel.cluster.server.AbstractTimeBasedTest;
import com.alibaba.csp.sentinel.util.TimeUtil;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.MockedStatic;
public class ClusterMetricTest extends AbstractTimeBasedTest {
@Test
public void testTryOccupyNext() {
setCurrentMillis(System.currentTimeMillis());
ClusterMetric metric = new ClusterMetric(5, 25);
metric.add(ClusterFlowEvent.PASS, 1);
metric.add(ClusterFlowEvent.PASS, 2);
metric.add(ClusterFlowEvent.PASS, 1);
metric.add(ClusterFlowEvent.BLOCK, 1);
Assert.assertEquals(4, metric.getSum(ClusterFlowEvent.PASS));
Assert.assertEquals(1, metric.getSum(ClusterFlowEvent.BLOCK));
Assert.assertEquals(160, metric.getAvg(ClusterFlowEvent.PASS), 0.01);
Assert.assertEquals(200, metric.tryOccupyNext(ClusterFlowEvent.PASS, 111, 900));
metric.add(ClusterFlowEvent.PASS, 1);
metric.add(ClusterFlowEvent.PASS, 2);
metric.add(ClusterFlowEvent.PASS, 1);
Assert.assertEquals(200, metric.tryOccupyNext(ClusterFlowEvent.PASS, 222, 900));
metric.add(ClusterFlowEvent.PASS, 1);
metric.add(ClusterFlowEvent.PASS, 2);
metric.add(ClusterFlowEvent.PASS, 1);
Assert.assertEquals(0, metric.tryOccupyNext(ClusterFlowEvent.PASS, 333, 900));
try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
setCurrentMillis(mocked, System.currentTimeMillis());
ClusterMetric metric = new ClusterMetric(5, 25);
metric.add(ClusterFlowEvent.PASS, 1);
metric.add(ClusterFlowEvent.PASS, 2);
metric.add(ClusterFlowEvent.PASS, 1);
metric.add(ClusterFlowEvent.BLOCK, 1);
Assert.assertEquals(4, metric.getSum(ClusterFlowEvent.PASS));
Assert.assertEquals(1, metric.getSum(ClusterFlowEvent.BLOCK));
Assert.assertEquals(160, metric.getAvg(ClusterFlowEvent.PASS), 0.01);
Assert.assertEquals(200, metric.tryOccupyNext(ClusterFlowEvent.PASS, 111, 900));
metric.add(ClusterFlowEvent.PASS, 1);
metric.add(ClusterFlowEvent.PASS, 2);
metric.add(ClusterFlowEvent.PASS, 1);
Assert.assertEquals(200, metric.tryOccupyNext(ClusterFlowEvent.PASS, 222, 900));
metric.add(ClusterFlowEvent.PASS, 1);
metric.add(ClusterFlowEvent.PASS, 2);
metric.add(ClusterFlowEvent.PASS, 1);
Assert.assertEquals(0, metric.tryOccupyNext(ClusterFlowEvent.PASS, 333, 900));
}
}
}

View File

@ -15,9 +15,11 @@
*/
package com.alibaba.csp.sentinel.cluster.flow.statistic.metric;
import com.alibaba.csp.sentinel.cluster.test.AbstractTimeBasedTest;
import com.alibaba.csp.sentinel.cluster.server.AbstractTimeBasedTest;
import com.alibaba.csp.sentinel.util.TimeUtil;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.MockedStatic;
import java.util.HashMap;
import java.util.Map;
@ -26,26 +28,28 @@ public class ClusterParamMetricTest extends AbstractTimeBasedTest {
@Test
public void testClusterParamMetric() {
setCurrentMillis(System.currentTimeMillis());
Map<Object, Double> topMap = new HashMap<Object, Double>();
ClusterParamMetric metric = new ClusterParamMetric(5, 25, 100);
metric.addValue("e1", -1);
metric.addValue("e1", -2);
metric.addValue("e2", 100);
metric.addValue("e2", 23);
metric.addValue("e3", 100);
metric.addValue("e3", 230);
Assert.assertEquals(-3, metric.getSum("e1"));
Assert.assertEquals(-120, metric.getAvg("e1"), 0.01);
topMap.put("e3", (double) 13200);
Assert.assertEquals(topMap, metric.getTopValues(1));
topMap.put("e2", (double) 4920);
topMap.put("e1", (double) -120);
Assert.assertEquals(topMap, metric.getTopValues(5));
metric.addValue("e2", 100);
metric.addValue("e2", 23);
Assert.assertEquals(246, metric.getSum("e2"));
Assert.assertEquals(9840, metric.getAvg("e2"), 0.01);
try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
setCurrentMillis(mocked, System.currentTimeMillis());
Map<Object, Double> topMap = new HashMap<Object, Double>();
ClusterParamMetric metric = new ClusterParamMetric(5, 25, 100);
metric.addValue("e1", -1);
metric.addValue("e1", -2);
metric.addValue("e2", 100);
metric.addValue("e2", 23);
metric.addValue("e3", 100);
metric.addValue("e3", 230);
Assert.assertEquals(-3, metric.getSum("e1"));
Assert.assertEquals(-120, metric.getAvg("e1"), 0.01);
topMap.put("e3", (double) 13200);
Assert.assertEquals(topMap, metric.getTopValues(1));
topMap.put("e2", (double) 4920);
topMap.put("e1", (double) -120);
Assert.assertEquals(topMap, metric.getTopValues(5));
metric.addValue("e2", 100);
metric.addValue("e2", 23);
Assert.assertEquals(246, metric.getSum("e2"));
Assert.assertEquals(9840, metric.getAvg("e2"), 0.01);
}
}
@Test(expected = IllegalArgumentException.class)

View File

@ -0,0 +1,55 @@
/*
* 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.csp.sentinel.cluster.server;
import com.alibaba.csp.sentinel.util.TimeUtil;
import org.junit.runner.RunWith;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
/**
* Mock support for {@link TimeUtil}.
*/
@RunWith(MockitoJUnitRunner.class)
public abstract class AbstractTimeBasedTest {
private long currentMillis = 0;
public MockedStatic<TimeUtil> mockTimeUtil() {
MockedStatic<TimeUtil> mocked = Mockito.mockStatic(TimeUtil.class);
mocked.when(TimeUtil::currentTimeMillis).thenReturn(currentMillis);
return mocked;
}
protected final void useActualTime(MockedStatic<TimeUtil> mocked) {
mocked.when(TimeUtil::currentTimeMillis).thenCallRealMethod();
}
protected final void setCurrentMillis(MockedStatic<TimeUtil> mocked, long cur) {
currentMillis = cur;
mocked.when(TimeUtil::currentTimeMillis).thenReturn(currentMillis);
}
protected final void sleep(MockedStatic<TimeUtil> mocked, long t) {
currentMillis += t;
mocked.when(TimeUtil::currentTimeMillis).thenReturn(currentMillis);
}
protected final void sleepSecond(MockedStatic<TimeUtil> mocked, long timeSec) {
sleep(mocked, timeSec * 1000);
}
}

View File

@ -1,55 +0,0 @@
/*
* 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.csp.sentinel.cluster.test;
import com.alibaba.csp.sentinel.util.TimeUtil;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
/**
* Mock support for {@link TimeUtil}.
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({TimeUtil.class})
public abstract class AbstractTimeBasedTest {
private long currentMillis = 0;
{
PowerMockito.mockStatic(TimeUtil.class);
PowerMockito.when(TimeUtil.currentTimeMillis()).thenReturn(currentMillis);
}
protected final void useActualTime() {
PowerMockito.when(TimeUtil.currentTimeMillis()).thenCallRealMethod();
}
protected final void setCurrentMillis(long cur) {
currentMillis = cur;
PowerMockito.when(TimeUtil.currentTimeMillis()).thenReturn(currentMillis);
}
protected final void sleep(int t) {
currentMillis += t;
PowerMockito.when(TimeUtil.currentTimeMillis()).thenReturn(currentMillis);
}
protected final void sleepSecond(int timeSec) {
sleep(timeSec * 1000);
}
}

View File

@ -1,57 +0,0 @@
/*
* 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.csp.sentinel.test;
import com.alibaba.csp.sentinel.util.TimeUtil;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
/**
* Mock support for {@link TimeUtil}
*
* @author jason
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({TimeUtil.class})
public abstract class AbstractTimeBasedTest {
private long currentMillis = 0;
{
PowerMockito.mockStatic(TimeUtil.class);
PowerMockito.when(TimeUtil.currentTimeMillis()).thenReturn(currentMillis);
}
protected final void useActualTime() {
PowerMockito.when(TimeUtil.currentTimeMillis()).thenCallRealMethod();
}
protected final void setCurrentMillis(long cur) {
currentMillis = cur;
PowerMockito.when(TimeUtil.currentTimeMillis()).thenReturn(currentMillis);
}
protected final void sleep(int t) {
currentMillis += t;
PowerMockito.when(TimeUtil.currentTimeMillis()).thenReturn(currentMillis);
}
protected final void sleepSecond(int timeSec) {
sleep(timeSec * 1000);
}
}

View File

@ -30,7 +30,7 @@
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<artifactId>mockito-inline</artifactId>
<scope>test</scope>
</dependency>
<dependency>
@ -43,16 +43,6 @@
<artifactId>java-hamcrest</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>

View File

@ -22,11 +22,14 @@ import com.alibaba.csp.sentinel.metric.extension.MetricExtensionProvider;
import com.alibaba.csp.sentinel.slotchain.StringResourceWrapper;
import com.alibaba.csp.sentinel.test.AbstractTimeBasedTest;
import com.alibaba.csp.sentinel.util.TimeUtil;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.MockedStatic;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.when;
/**
* @author Carpenter Lee
@ -35,32 +38,34 @@ public class MetricExitCallbackTest extends AbstractTimeBasedTest {
@Test
public void onExit() {
FakeMetricExtension extension = new FakeMetricExtension();
MetricExtensionProvider.addMetricExtension(extension);
try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
FakeMetricExtension extension = new FakeMetricExtension();
MetricExtensionProvider.addMetricExtension(extension);
MetricExitCallback exitCallback = new MetricExitCallback();
StringResourceWrapper resourceWrapper = new StringResourceWrapper("resource", EntryType.OUT);
int count = 2;
Object[] args = {"args1", "args2"};
long prevRt = 20;
extension.rt = prevRt;
extension.success = 6;
extension.thread = 10;
Context context = mock(Context.class);
Entry entry = mock(Entry.class);
MetricExitCallback exitCallback = new MetricExitCallback();
StringResourceWrapper resourceWrapper = new StringResourceWrapper("resource", EntryType.OUT);
int count = 2;
Object[] args = {"args1", "args2"};
long prevRt = 20;
extension.rt = prevRt;
extension.success = 6;
extension.thread = 10;
Context context = mock(Context.class);
Entry entry = mock(Entry.class);
// Mock current time
long curMillis = System.currentTimeMillis();
setCurrentMillis(curMillis);
// Mock current time
long curMillis = System.currentTimeMillis();
setCurrentMillis(mocked, curMillis);
int deltaMs = 100;
when(entry.getError()).thenReturn(null);
when(entry.getCreateTimestamp()).thenReturn(curMillis - deltaMs);
when(context.getCurEntry()).thenReturn(entry);
exitCallback.onExit(context, resourceWrapper, count, args);
Assert.assertEquals(prevRt + deltaMs, extension.rt);
Assert.assertEquals(extension.success, 6 + count);
Assert.assertEquals(extension.thread, 10 - 1);
int deltaMs = 100;
when(entry.getError()).thenReturn(null);
when(entry.getCreateTimestamp()).thenReturn(curMillis - deltaMs);
when(context.getCurEntry()).thenReturn(entry);
exitCallback.onExit(context, resourceWrapper, count, args);
Assert.assertEquals(prevRt + deltaMs, extension.rt);
Assert.assertEquals(extension.success, 6 + count);
Assert.assertEquals(extension.thread, 10 - 1);
}
}
/**
@ -68,31 +73,33 @@ public class MetricExitCallbackTest extends AbstractTimeBasedTest {
*/
@Test
public void advancedExtensionOnExit() {
FakeAdvancedMetricExtension extension = new FakeAdvancedMetricExtension();
MetricExtensionProvider.addMetricExtension(extension);
try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
FakeAdvancedMetricExtension extension = new FakeAdvancedMetricExtension();
MetricExtensionProvider.addMetricExtension(extension);
MetricExitCallback exitCallback = new MetricExitCallback();
StringResourceWrapper resourceWrapper = new StringResourceWrapper("resource", EntryType.OUT);
int count = 2;
Object[] args = {"args1", "args2"};
long prevRt = 20;
extension.rt = prevRt;
extension.complete = 6;
extension.concurrency = 10;
Context context = mock(Context.class);
Entry entry = mock(Entry.class);
MetricExitCallback exitCallback = new MetricExitCallback();
StringResourceWrapper resourceWrapper = new StringResourceWrapper("resource", EntryType.OUT);
int count = 2;
Object[] args = {"args1", "args2"};
long prevRt = 20;
extension.rt = prevRt;
extension.complete = 6;
extension.concurrency = 10;
Context context = mock(Context.class);
Entry entry = mock(Entry.class);
// Mock current time
long curMillis = System.currentTimeMillis();
setCurrentMillis(curMillis);
// Mock current time
long curMillis = System.currentTimeMillis();
setCurrentMillis(mocked, curMillis);
int deltaMs = 100;
when(entry.getError()).thenReturn(null);
when(entry.getCreateTimestamp()).thenReturn(curMillis - deltaMs);
when(context.getCurEntry()).thenReturn(entry);
exitCallback.onExit(context, resourceWrapper, count, args);
Assert.assertEquals(prevRt + deltaMs, extension.rt);
Assert.assertEquals(extension.complete, 6 + count);
Assert.assertEquals(extension.concurrency, 10 - 1);
int deltaMs = 100;
when(entry.getError()).thenReturn(null);
when(entry.getCreateTimestamp()).thenReturn(curMillis - deltaMs);
when(context.getCurEntry()).thenReturn(entry);
exitCallback.onExit(context, resourceWrapper, count, args);
Assert.assertEquals(prevRt + deltaMs, extension.rt);
Assert.assertEquals(extension.complete, 6 + count);
Assert.assertEquals(extension.concurrency, 10 - 1);
}
}
}

View File

@ -22,9 +22,11 @@ import com.alibaba.csp.sentinel.slots.block.degrade.circuitbreaker.CircuitBreake
import com.alibaba.csp.sentinel.slots.block.degrade.circuitbreaker.EventObserverRegistry;
import com.alibaba.csp.sentinel.test.AbstractTimeBasedTest;
import com.alibaba.csp.sentinel.util.TimeUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.MockedStatic;
import java.util.ArrayList;
import java.util.Arrays;
@ -55,180 +57,186 @@ public class CircuitBreakingIntegrationTest extends AbstractTimeBasedTest {
@Test
public void testSlowRequestMode() {
CircuitBreakerStateChangeObserver observer = mock(CircuitBreakerStateChangeObserver.class);
setCurrentMillis(System.currentTimeMillis() / 1000 * 1000);
int retryTimeoutSec = 5;
int maxRt = 50;
int statIntervalMs = 20000;
int minRequestAmount = 10;
String res = "CircuitBreakingIntegrationTest_testSlowRequestMode";
EventObserverRegistry.getInstance().addStateChangeObserver(res, observer);
DegradeRuleManager.loadRules(Arrays.asList(
new DegradeRule(res).setTimeWindow(retryTimeoutSec).setCount(maxRt)
.setStatIntervalMs(statIntervalMs).setMinRequestAmount(minRequestAmount)
.setSlowRatioThreshold(0.8d).setGrade(0)
));
try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
CircuitBreakerStateChangeObserver observer = mock(CircuitBreakerStateChangeObserver.class);
setCurrentMillis(mocked, System.currentTimeMillis() / 1000 * 1000);
int retryTimeoutSec = 5;
int maxRt = 50;
int statIntervalMs = 20000;
int minRequestAmount = 10;
String res = "CircuitBreakingIntegrationTest_testSlowRequestMode";
EventObserverRegistry.getInstance().addStateChangeObserver(res, observer);
DegradeRuleManager.loadRules(Arrays.asList(
new DegradeRule(res).setTimeWindow(retryTimeoutSec).setCount(maxRt)
.setStatIntervalMs(statIntervalMs).setMinRequestAmount(minRequestAmount)
.setSlowRatioThreshold(0.8d).setGrade(0)
));
// Try first N requests where N = minRequestAmount.
for (int i = 0; i < minRequestAmount; i++) {
if (i < 7) {
assertTrue(entryAndSleepFor(res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
} else {
assertTrue(entryAndSleepFor(res, maxRt + ThreadLocalRandom.current().nextInt(-20, -10)));
// Try first N requests where N = minRequestAmount.
for (int i = 0; i < minRequestAmount; i++) {
if (i < 7) {
assertTrue(entryAndSleepFor(mocked, res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
} else {
assertTrue(entryAndSleepFor(mocked, res, maxRt + ThreadLocalRandom.current().nextInt(-20, -10)));
}
}
// Till now slow ratio should be 70%.
assertTrue(entryAndSleepFor(mocked, res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
assertTrue(entryAndSleepFor(mocked, res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
assertTrue(entryAndSleepFor(mocked, res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
assertTrue(entryAndSleepFor(mocked, res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
assertTrue(entryAndSleepFor(mocked, res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
assertTrue(entryAndSleepFor(mocked, res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
// Circuit breaker has transformed to OPEN since here.
verify(observer)
.onStateChange(eq(State.CLOSED), eq(State.OPEN), any(DegradeRule.class), anyDouble());
assertEquals(State.OPEN, DegradeRuleManager.getCircuitBreakers(res).get(0).currentState());
assertFalse(entryAndSleepFor(mocked, res, 1));
sleepSecond(mocked, 1);
assertFalse(entryAndSleepFor(mocked, res, 1));
sleepSecond(mocked, retryTimeoutSec);
// Test HALF-OPEN to OPEN.
assertTrue(entryAndSleepFor(mocked, res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
verify(observer)
.onStateChange(eq(State.OPEN), eq(State.HALF_OPEN), any(DegradeRule.class), nullable(Double.class));
verify(observer)
.onStateChange(eq(State.HALF_OPEN), eq(State.OPEN), any(DegradeRule.class), anyDouble());
// Wait for next retry timeout;
reset(observer);
sleepSecond(mocked, retryTimeoutSec + 1);
assertTrue(entryAndSleepFor(mocked, res, maxRt - ThreadLocalRandom.current().nextInt(10, 20)));
verify(observer)
.onStateChange(eq(State.OPEN), eq(State.HALF_OPEN), any(DegradeRule.class), nullable(Double.class));
verify(observer)
.onStateChange(eq(State.HALF_OPEN), eq(State.CLOSED), any(DegradeRule.class), nullable(Double.class));
// Now circuit breaker has been closed.
assertTrue(entryAndSleepFor(mocked, res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
EventObserverRegistry.getInstance().removeStateChangeObserver(res);
}
// Till now slow ratio should be 70%.
assertTrue(entryAndSleepFor(res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
assertTrue(entryAndSleepFor(res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
assertTrue(entryAndSleepFor(res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
assertTrue(entryAndSleepFor(res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
assertTrue(entryAndSleepFor(res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
assertTrue(entryAndSleepFor(res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
// Circuit breaker has transformed to OPEN since here.
verify(observer)
.onStateChange(eq(State.CLOSED), eq(State.OPEN), any(DegradeRule.class), anyDouble());
assertEquals(State.OPEN, DegradeRuleManager.getCircuitBreakers(res).get(0).currentState());
assertFalse(entryAndSleepFor(res, 1));
sleepSecond(1);
assertFalse(entryAndSleepFor(res, 1));
sleepSecond(retryTimeoutSec);
// Test HALF-OPEN to OPEN.
assertTrue(entryAndSleepFor(res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
verify(observer)
.onStateChange(eq(State.OPEN), eq(State.HALF_OPEN), any(DegradeRule.class), nullable(Double.class));
verify(observer)
.onStateChange(eq(State.HALF_OPEN), eq(State.OPEN), any(DegradeRule.class), anyDouble());
// Wait for next retry timeout;
reset(observer);
sleepSecond(retryTimeoutSec + 1);
assertTrue(entryAndSleepFor(res, maxRt - ThreadLocalRandom.current().nextInt(10, 20)));
verify(observer)
.onStateChange(eq(State.OPEN), eq(State.HALF_OPEN), any(DegradeRule.class), nullable(Double.class));
verify(observer)
.onStateChange(eq(State.HALF_OPEN), eq(State.CLOSED), any(DegradeRule.class), nullable(Double.class));
// Now circuit breaker has been closed.
assertTrue(entryAndSleepFor(res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
EventObserverRegistry.getInstance().removeStateChangeObserver(res);
}
@Test
public void testSlowRequestModeUseDefaultRule() {
CircuitBreakerStateChangeObserver observer = mock(CircuitBreakerStateChangeObserver.class);
setCurrentMillis(System.currentTimeMillis() / 1000 * 1000);
int retryTimeoutSec = 5;
int maxRt = 50;
int statIntervalMs = 20000;
int minRequestAmount = 10;
String res = "CircuitBreakingIntegrationTest_testSlowRequestModeUseDefaultRule";
EventObserverRegistry.getInstance().addStateChangeObserver(res, observer);
try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
CircuitBreakerStateChangeObserver observer = mock(CircuitBreakerStateChangeObserver.class);
setCurrentMillis(mocked, System.currentTimeMillis() / 1000 * 1000);
int retryTimeoutSec = 5;
int maxRt = 50;
int statIntervalMs = 20000;
int minRequestAmount = 10;
String res = "CircuitBreakingIntegrationTest_testSlowRequestModeUseDefaultRule";
EventObserverRegistry.getInstance().addStateChangeObserver(res, observer);
DefaultCircuitBreakerRuleManager.loadRules(Arrays.asList(
new DegradeRule(DefaultCircuitBreakerRuleManager.DEFAULT_KEY).setTimeWindow(retryTimeoutSec).setCount(maxRt)
.setStatIntervalMs(statIntervalMs).setMinRequestAmount(minRequestAmount)
.setSlowRatioThreshold(0.8d).setGrade(0)));
DefaultCircuitBreakerRuleManager.loadRules(Arrays.asList(
new DegradeRule(DefaultCircuitBreakerRuleManager.DEFAULT_KEY).setTimeWindow(retryTimeoutSec).setCount(maxRt)
.setStatIntervalMs(statIntervalMs).setMinRequestAmount(minRequestAmount)
.setSlowRatioThreshold(0.8d).setGrade(0)));
// Try first N requests where N = minRequestAmount.
for (int i = 0; i < minRequestAmount; i++) {
if (i < 7) {
assertTrue(entryAndSleepFor(res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
} else {
assertTrue(entryAndSleepFor(res, maxRt + ThreadLocalRandom.current().nextInt(-20, -10)));
// Try first N requests where N = minRequestAmount.
for (int i = 0; i < minRequestAmount; i++) {
if (i < 7) {
assertTrue(entryAndSleepFor(mocked, res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
} else {
assertTrue(entryAndSleepFor(mocked, res, maxRt + ThreadLocalRandom.current().nextInt(-20, -10)));
}
}
// Till now slow ratio should be 70%.
assertTrue(entryAndSleepFor(mocked, res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
assertTrue(entryAndSleepFor(mocked, res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
assertTrue(entryAndSleepFor(mocked, res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
assertTrue(entryAndSleepFor(mocked, res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
assertTrue(entryAndSleepFor(mocked, res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
assertTrue(entryAndSleepFor(mocked, res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
// Circuit breaker has transformed to OPEN since here.
verify(observer)
.onStateChange(eq(State.CLOSED), eq(State.OPEN), any(DegradeRule.class), anyDouble());
assertEquals(State.OPEN, DefaultCircuitBreakerRuleManager.getDefaultCircuitBreakers(res).get(0).currentState());
assertFalse(entryAndSleepFor(mocked, res, 1));
sleepSecond(mocked, 1);
assertFalse(entryAndSleepFor(mocked, res, 1));
sleepSecond(mocked, retryTimeoutSec);
// Test HALF-OPEN to OPEN.
assertTrue(entryAndSleepFor(mocked, res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
verify(observer)
.onStateChange(eq(State.OPEN), eq(State.HALF_OPEN), any(DegradeRule.class), nullable(Double.class));
verify(observer)
.onStateChange(eq(State.HALF_OPEN), eq(State.OPEN), any(DegradeRule.class), anyDouble());
// Wait for next retry timeout;
reset(observer);
sleepSecond(mocked, retryTimeoutSec + 1);
assertTrue(entryAndSleepFor(mocked, res, maxRt - ThreadLocalRandom.current().nextInt(10, 20)));
verify(observer)
.onStateChange(eq(State.OPEN), eq(State.HALF_OPEN), any(DegradeRule.class), nullable(Double.class));
verify(observer)
.onStateChange(eq(State.HALF_OPEN), eq(State.CLOSED), any(DegradeRule.class), nullable(Double.class));
// Now circuit breaker has been closed.
assertTrue(entryAndSleepFor(mocked, res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
EventObserverRegistry.getInstance().removeStateChangeObserver(res);
}
// Till now slow ratio should be 70%.
assertTrue(entryAndSleepFor(res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
assertTrue(entryAndSleepFor(res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
assertTrue(entryAndSleepFor(res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
assertTrue(entryAndSleepFor(res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
assertTrue(entryAndSleepFor(res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
assertTrue(entryAndSleepFor(res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
// Circuit breaker has transformed to OPEN since here.
verify(observer)
.onStateChange(eq(State.CLOSED), eq(State.OPEN), any(DegradeRule.class), anyDouble());
assertEquals(State.OPEN, DefaultCircuitBreakerRuleManager.getDefaultCircuitBreakers(res).get(0).currentState());
assertFalse(entryAndSleepFor(res, 1));
sleepSecond(1);
assertFalse(entryAndSleepFor(res, 1));
sleepSecond(retryTimeoutSec);
// Test HALF-OPEN to OPEN.
assertTrue(entryAndSleepFor(res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
verify(observer)
.onStateChange(eq(State.OPEN), eq(State.HALF_OPEN), any(DegradeRule.class), nullable(Double.class));
verify(observer)
.onStateChange(eq(State.HALF_OPEN), eq(State.OPEN), any(DegradeRule.class), anyDouble());
// Wait for next retry timeout;
reset(observer);
sleepSecond(retryTimeoutSec + 1);
assertTrue(entryAndSleepFor(res, maxRt - ThreadLocalRandom.current().nextInt(10, 20)));
verify(observer)
.onStateChange(eq(State.OPEN), eq(State.HALF_OPEN), any(DegradeRule.class), nullable(Double.class));
verify(observer)
.onStateChange(eq(State.HALF_OPEN), eq(State.CLOSED), any(DegradeRule.class), nullable(Double.class));
// Now circuit breaker has been closed.
assertTrue(entryAndSleepFor(res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
EventObserverRegistry.getInstance().removeStateChangeObserver(res);
}
@Test
public void testExceptionRatioMode() {
CircuitBreakerStateChangeObserver observer = mock(CircuitBreakerStateChangeObserver.class);
setCurrentMillis(System.currentTimeMillis() / 1000 * 1000);
int retryTimeoutSec = 5;
double maxRatio = 0.5;
int statIntervalMs = 25000;
final int minRequestAmount = 10;
String res = "CircuitBreakingIntegrationTest_testExceptionRatioMode";
EventObserverRegistry.getInstance().addStateChangeObserver(res, observer);
DegradeRuleManager.loadRules(Arrays.asList(
new DegradeRule(res).setTimeWindow(retryTimeoutSec).setCount(maxRatio)
.setStatIntervalMs(statIntervalMs).setMinRequestAmount(minRequestAmount)
.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO)
));
try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
CircuitBreakerStateChangeObserver observer = mock(CircuitBreakerStateChangeObserver.class);
setCurrentMillis(mocked, System.currentTimeMillis() / 1000 * 1000);
int retryTimeoutSec = 5;
double maxRatio = 0.5;
int statIntervalMs = 25000;
final int minRequestAmount = 10;
String res = "CircuitBreakingIntegrationTest_testExceptionRatioMode";
EventObserverRegistry.getInstance().addStateChangeObserver(res, observer);
DegradeRuleManager.loadRules(Arrays.asList(
new DegradeRule(res).setTimeWindow(retryTimeoutSec).setCount(maxRatio)
.setStatIntervalMs(statIntervalMs).setMinRequestAmount(minRequestAmount)
.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO)
));
// Try first N requests where N = minRequestAmount.
for (int i = 0; i < minRequestAmount - 1; i++) {
if (i < 6) {
assertTrue(entryWithErrorIfPresent(res, new IllegalArgumentException()));
} else {
assertTrue(entryWithErrorIfPresent(res, null));
// Try first N requests where N = minRequestAmount.
for (int i = 0; i < minRequestAmount - 1; i++) {
if (i < 6) {
assertTrue(entryWithErrorIfPresent(mocked, res, new IllegalArgumentException()));
} else {
assertTrue(entryWithErrorIfPresent(mocked, res, null));
}
}
// Till now slow ratio should be 60%.
assertTrue(entryWithErrorIfPresent(mocked, res, new IllegalArgumentException()));
// Circuit breaker has transformed to OPEN since here.
assertEquals(State.OPEN, DegradeRuleManager.getCircuitBreakers(res).get(0).currentState());
assertFalse(entryWithErrorIfPresent(mocked, res, null));
sleepSecond(mocked, 2);
assertFalse(entryWithErrorIfPresent(mocked, res, null));
sleepSecond(mocked, retryTimeoutSec);
// Test HALF-OPEN to OPEN.
assertTrue(entryWithErrorIfPresent(mocked, res, new IllegalArgumentException()));
verify(observer)
.onStateChange(eq(State.OPEN), eq(State.HALF_OPEN), any(DegradeRule.class), nullable(Double.class));
verify(observer)
.onStateChange(eq(State.HALF_OPEN), eq(State.OPEN), any(DegradeRule.class), anyDouble());
// Wait for next retry timeout;
reset(observer);
sleepSecond(mocked, retryTimeoutSec + 1);
assertTrue(entryWithErrorIfPresent(mocked, res, null));
verify(observer)
.onStateChange(eq(State.OPEN), eq(State.HALF_OPEN), any(DegradeRule.class), nullable(Double.class));
verify(observer)
.onStateChange(eq(State.HALF_OPEN), eq(State.CLOSED), any(DegradeRule.class), nullable(Double.class));
// Now circuit breaker has been closed.
assertTrue(entryWithErrorIfPresent(mocked, res, new IllegalArgumentException()));
EventObserverRegistry.getInstance().removeStateChangeObserver(res);
}
// Till now slow ratio should be 60%.
assertTrue(entryWithErrorIfPresent(res, new IllegalArgumentException()));
// Circuit breaker has transformed to OPEN since here.
assertEquals(State.OPEN, DegradeRuleManager.getCircuitBreakers(res).get(0).currentState());
assertFalse(entryWithErrorIfPresent(res, null));
sleepSecond(2);
assertFalse(entryWithErrorIfPresent(res, null));
sleepSecond(retryTimeoutSec);
// Test HALF-OPEN to OPEN.
assertTrue(entryWithErrorIfPresent(res, new IllegalArgumentException()));
verify(observer)
.onStateChange(eq(State.OPEN), eq(State.HALF_OPEN), any(DegradeRule.class), nullable(Double.class));
verify(observer)
.onStateChange(eq(State.HALF_OPEN), eq(State.OPEN), any(DegradeRule.class), anyDouble());
// Wait for next retry timeout;
reset(observer);
sleepSecond(retryTimeoutSec + 1);
assertTrue(entryWithErrorIfPresent(res, null));
verify(observer)
.onStateChange(eq(State.OPEN), eq(State.HALF_OPEN), any(DegradeRule.class), nullable(Double.class));
verify(observer)
.onStateChange(eq(State.HALF_OPEN), eq(State.CLOSED), any(DegradeRule.class), nullable(Double.class));
// Now circuit breaker has been closed.
assertTrue(entryWithErrorIfPresent(res, new IllegalArgumentException()));
EventObserverRegistry.getInstance().removeStateChangeObserver(res);
}
@Test
@ -252,45 +260,47 @@ public class CircuitBreakingIntegrationTest extends AbstractTimeBasedTest {
@Test
public void testMultipleHalfOpenedBreakers() {
CircuitBreakerStateChangeObserver observer = mock(CircuitBreakerStateChangeObserver.class);
setCurrentMillis(System.currentTimeMillis() / 1000 * 1000);
int retryTimeoutSec = 2;
int maxRt = 50;
int statIntervalMs = 20000;
int minRequestAmount = 1;
String res = "CircuitBreakingIntegrationTest_testMultipleHalfOpenedBreakers";
EventObserverRegistry.getInstance().addStateChangeObserver(res, observer);
// initial two rules
DegradeRuleManager.loadRules(Arrays.asList(
new DegradeRule(res).setTimeWindow(retryTimeoutSec).setCount(maxRt)
.setStatIntervalMs(statIntervalMs).setMinRequestAmount(minRequestAmount)
.setSlowRatioThreshold(0.8d).setGrade(0),
new DegradeRule(res).setTimeWindow(retryTimeoutSec * 2).setCount(maxRt)
.setStatIntervalMs(statIntervalMs).setMinRequestAmount(minRequestAmount)
.setSlowRatioThreshold(0.8d).setGrade(0)
));
assertTrue(entryAndSleepFor(res, 100));
// they are open now
for (CircuitBreaker breaker : DegradeRuleManager.getCircuitBreakers(res)) {
assertEquals(CircuitBreaker.State.OPEN, breaker.currentState());
try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
CircuitBreakerStateChangeObserver observer = mock(CircuitBreakerStateChangeObserver.class);
setCurrentMillis(mocked, System.currentTimeMillis() / 1000 * 1000);
int retryTimeoutSec = 2;
int maxRt = 50;
int statIntervalMs = 20000;
int minRequestAmount = 1;
String res = "CircuitBreakingIntegrationTest_testMultipleHalfOpenedBreakers";
EventObserverRegistry.getInstance().addStateChangeObserver(res, observer);
// initial two rules
DegradeRuleManager.loadRules(Arrays.asList(
new DegradeRule(res).setTimeWindow(retryTimeoutSec).setCount(maxRt)
.setStatIntervalMs(statIntervalMs).setMinRequestAmount(minRequestAmount)
.setSlowRatioThreshold(0.8d).setGrade(0),
new DegradeRule(res).setTimeWindow(retryTimeoutSec * 2).setCount(maxRt)
.setStatIntervalMs(statIntervalMs).setMinRequestAmount(minRequestAmount)
.setSlowRatioThreshold(0.8d).setGrade(0)
));
assertTrue(entryAndSleepFor(mocked, res, 100));
// they are open now
for (CircuitBreaker breaker : DegradeRuleManager.getCircuitBreakers(res)) {
assertEquals(CircuitBreaker.State.OPEN, breaker.currentState());
}
sleepSecond(mocked, 3);
for (int i = 0; i < 10; i++) {
assertFalse(entryAndSleepFor(mocked, res, 100));
}
// Now one is in open state while the other experiences open -> half-open -> open
verifyState(DegradeRuleManager.getCircuitBreakers(res), 2);
sleepSecond(mocked, 3);
// They will all recover
for (int i = 0; i < 10; i++) {
assertTrue(entryAndSleepFor(mocked, res, 1));
}
verifyState(DegradeRuleManager.getCircuitBreakers(res), -4);
}
sleepSecond(3);
for (int i = 0; i < 10; i ++) {
assertFalse(entryAndSleepFor(res, 100));
}
// Now one is in open state while the other experiences open -> half-open -> open
verifyState(DegradeRuleManager.getCircuitBreakers(res), 2);
sleepSecond(3);
// They will all recover
for (int i = 0; i < 10; i ++) {
assertTrue(entryAndSleepFor(res, 1));
}
verifyState(DegradeRuleManager.getCircuitBreakers(res), -4);
}
}

View File

@ -21,6 +21,7 @@ import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Arrays;
import com.alibaba.csp.sentinel.util.TimeUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@ -30,6 +31,7 @@ import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.test.AbstractTimeBasedTest;
import org.mockito.MockedStatic;
/**
* @author Eric Zhao
@ -48,38 +50,40 @@ public class ExceptionCircuitBreakerTest extends AbstractTimeBasedTest {
@Test
public void testRecordErrorOrSuccess() throws BlockException {
String resource = "testRecordErrorOrSuccess";
int retryTimeoutMillis = 10 * 1000;
int retryTimeout = retryTimeoutMillis / 1000;
DegradeRule rule = new DegradeRule("abc")
.setCount(0.2d)
.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO)
.setStatIntervalMs(20 * 1000)
.setTimeWindow(retryTimeout)
.setMinRequestAmount(1);
rule.setResource(resource);
DegradeRuleManager.loadRules(Arrays.asList(rule));
try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
String resource = "testRecordErrorOrSuccess";
int retryTimeoutMillis = 10 * 1000;
int retryTimeout = retryTimeoutMillis / 1000;
DegradeRule rule = new DegradeRule("abc")
.setCount(0.2d)
.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO)
.setStatIntervalMs(20 * 1000)
.setTimeWindow(retryTimeout)
.setMinRequestAmount(1);
rule.setResource(resource);
DegradeRuleManager.loadRules(Arrays.asList(rule));
assertTrue(entryAndSleepFor(resource, 10));
assertTrue(entryAndSleepFor(mocked, resource, 10));
assertTrue(entryWithErrorIfPresent(resource, new IllegalArgumentException())); // -> open
assertFalse(entryWithErrorIfPresent(resource, new IllegalArgumentException()));
assertFalse(entryAndSleepFor(resource, 100));
sleep(retryTimeoutMillis / 2);
assertFalse(entryAndSleepFor(resource, 100));
sleep(retryTimeoutMillis / 2);
assertTrue(entryWithErrorIfPresent(resource, new IllegalArgumentException())); // -> half -> open
assertFalse(entryAndSleepFor(resource, 100));
assertFalse(entryAndSleepFor(resource, 100));
sleep(retryTimeoutMillis);
assertTrue(entryAndSleepFor(resource, 100)); // -> half -> closed
assertTrue(entryAndSleepFor(resource, 100));
assertTrue(entryAndSleepFor(resource, 100));
assertTrue(entryAndSleepFor(resource, 100));
assertTrue(entryAndSleepFor(resource, 100));
assertTrue(entryAndSleepFor(resource, 100));
assertTrue(entryAndSleepFor(resource, 100));
assertTrue(entryWithErrorIfPresent(resource, new IllegalArgumentException()));
assertTrue(entryAndSleepFor(resource, 100));
assertTrue(entryWithErrorIfPresent(mocked, resource, new IllegalArgumentException())); // -> open
assertFalse(entryWithErrorIfPresent(mocked, resource, new IllegalArgumentException()));
assertFalse(entryAndSleepFor(mocked, resource, 100));
sleep(mocked, retryTimeoutMillis / 2);
assertFalse(entryAndSleepFor(mocked, resource, 100));
sleep(mocked, retryTimeoutMillis / 2);
assertTrue(entryWithErrorIfPresent(mocked, resource, new IllegalArgumentException())); // -> half -> open
assertFalse(entryAndSleepFor(mocked, resource, 100));
assertFalse(entryAndSleepFor(mocked, resource, 100));
sleep(mocked, retryTimeoutMillis);
assertTrue(entryAndSleepFor(mocked, resource, 100)); // -> half -> closed
assertTrue(entryAndSleepFor(mocked, resource, 100));
assertTrue(entryAndSleepFor(mocked, resource, 100));
assertTrue(entryAndSleepFor(mocked, resource, 100));
assertTrue(entryAndSleepFor(mocked, resource, 100));
assertTrue(entryAndSleepFor(mocked, resource, 100));
assertTrue(entryAndSleepFor(mocked, resource, 100));
assertTrue(entryWithErrorIfPresent(mocked, resource, new IllegalArgumentException()));
assertTrue(entryAndSleepFor(mocked, resource, 100));
}
}
}

View File

@ -4,9 +4,11 @@ import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.test.AbstractTimeBasedTest;
import com.alibaba.csp.sentinel.util.TimeUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.MockedStatic;
import java.util.ArrayList;
import java.util.Collections;
@ -31,28 +33,30 @@ public class ResponseTimeCircuitBreakerTest extends AbstractTimeBasedTest {
@Test
public void testMaxSlowRatioThreshold() {
String resource = "testMaxSlowRatioThreshold";
DegradeRule rule = new DegradeRule("resource")
.setCount(10)
.setGrade(RuleConstant.DEGRADE_GRADE_RT)
.setMinRequestAmount(3)
.setSlowRatioThreshold(1)
.setStatIntervalMs(5000)
.setTimeWindow(5);
rule.setResource(resource);
DegradeRuleManager.loadRules(Collections.singletonList(rule));
try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
String resource = "testMaxSlowRatioThreshold";
DegradeRule rule = new DegradeRule("resource")
.setCount(10)
.setGrade(RuleConstant.DEGRADE_GRADE_RT)
.setMinRequestAmount(3)
.setSlowRatioThreshold(1)
.setStatIntervalMs(5000)
.setTimeWindow(5);
rule.setResource(resource);
DegradeRuleManager.loadRules(Collections.singletonList(rule));
assertTrue(entryAndSleepFor(resource, 20));
assertTrue(entryAndSleepFor(resource, 20));
assertTrue(entryAndSleepFor(resource, 20));
assertTrue(entryAndSleepFor(mocked, resource, 20));
assertTrue(entryAndSleepFor(mocked, resource, 20));
assertTrue(entryAndSleepFor(mocked, resource, 20));
// should be blocked, cause 3/3 requests' rt is bigger than max rt.
assertFalse(entryAndSleepFor(resource,20));
sleep(1000);
assertFalse(entryAndSleepFor(resource,20));
sleep(4000);
// should be blocked, cause 3/3 requests' rt is bigger than max rt.
assertFalse(entryAndSleepFor(mocked, resource, 20));
sleep(mocked, 1000);
assertFalse(entryAndSleepFor(mocked, resource, 20));
sleep(mocked, 4000);
assertTrue(entryAndSleepFor(resource, 20));
assertTrue(entryAndSleepFor(mocked, resource, 20));
}
}
}

View File

@ -20,10 +20,12 @@ import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import com.alibaba.csp.sentinel.util.TimeUtil;
import org.junit.Test;
import com.alibaba.csp.sentinel.node.Node;
import com.alibaba.csp.sentinel.test.AbstractTimeBasedTest;
import org.mockito.MockedStatic;
/**
* @author jialiang.linjl
@ -32,32 +34,34 @@ public class WarmUpControllerTest extends AbstractTimeBasedTest {
@Test
public void testWarmUp() throws InterruptedException {
WarmUpController warmupController = new WarmUpController(10, 10, 3);
try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
WarmUpController warmupController = new WarmUpController(10, 10, 3);
setCurrentMillis(System.currentTimeMillis());
setCurrentMillis(mocked, System.currentTimeMillis());
Node node = mock(Node.class);
Node node = mock(Node.class);
when(node.passQps()).thenReturn(8d);
when(node.previousPassQps()).thenReturn(1d);
when(node.passQps()).thenReturn(8d);
when(node.previousPassQps()).thenReturn(1d);
assertFalse(warmupController.canPass(node, 1));
assertFalse(warmupController.canPass(node, 1));
when(node.passQps()).thenReturn(1d);
when(node.previousPassQps()).thenReturn(1d);
when(node.passQps()).thenReturn(1d);
when(node.previousPassQps()).thenReturn(1d);
assertTrue(warmupController.canPass(node, 1));
assertTrue(warmupController.canPass(node, 1));
when(node.previousPassQps()).thenReturn(10d);
when(node.previousPassQps()).thenReturn(10d);
for (int i = 0; i < 100; i++) {
sleep(100);
warmupController.canPass(node, 1);
for (int i = 0; i < 100; i++) {
sleep(mocked, 100);
warmupController.canPass(node, 1);
}
when(node.passQps()).thenReturn(8d);
assertTrue(warmupController.canPass(node, 1));
when(node.passQps()).thenReturn(10d);
assertFalse(warmupController.canPass(node, 1));
}
when(node.passQps()).thenReturn(8d);
assertTrue(warmupController.canPass(node, 1));
when(node.passQps()).thenReturn(10d);
assertFalse(warmupController.canPass(node, 1));
}
}

View File

@ -17,9 +17,11 @@ package com.alibaba.csp.sentinel.slots.block.flow.tokenbucket;
import com.alibaba.csp.sentinel.concurrent.NamedThreadFactory;
import com.alibaba.csp.sentinel.test.AbstractTimeBasedTest;
import com.alibaba.csp.sentinel.util.TimeUtil;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.MockedStatic;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
@ -52,74 +54,78 @@ public class TokenBucketTest extends AbstractTimeBasedTest {
@Test
public void testForDefaultTokenBucket() throws InterruptedException {
long unitProduceNum = 1;
long maxTokenNum = 2;
long intervalInMs = 1000;
long testStart = System.currentTimeMillis();
setCurrentMillis(testStart);
try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
long unitProduceNum = 1;
long maxTokenNum = 2;
long intervalInMs = 1000;
long testStart = System.currentTimeMillis();
setCurrentMillis(mocked, testStart);
DefaultTokenBucket defaultTokenBucket = new DefaultTokenBucket(unitProduceNum, maxTokenNum, intervalInMs);
DefaultTokenBucket defaultTokenBucket = new DefaultTokenBucket(unitProduceNum, maxTokenNum, intervalInMs);
assertTrue(defaultTokenBucket.tryConsume(1));
assertFalse(defaultTokenBucket.tryConsume(1));
assertTrue(defaultTokenBucket.tryConsume(1));
assertFalse(defaultTokenBucket.tryConsume(1));
DefaultTokenBucket defaultTokenBucketFullStart = new DefaultTokenBucket(unitProduceNum, maxTokenNum,
true, intervalInMs);
DefaultTokenBucket defaultTokenBucketFullStart = new DefaultTokenBucket(unitProduceNum, maxTokenNum,
true, intervalInMs);
assertTrue(defaultTokenBucketFullStart.tryConsume(2));
assertFalse(defaultTokenBucketFullStart.tryConsume(1));
assertTrue(defaultTokenBucketFullStart.tryConsume(2));
assertFalse(defaultTokenBucketFullStart.tryConsume(1));
sleep(1000);
assertTrue(defaultTokenBucket.tryConsume(1));
assertFalse(defaultTokenBucket.tryConsume(1));
sleep(mocked, 1000);
assertTrue(defaultTokenBucket.tryConsume(1));
assertFalse(defaultTokenBucket.tryConsume(1));
sleep(1000);
assertTrue(defaultTokenBucketFullStart.tryConsume(2));
assertFalse(defaultTokenBucketFullStart.tryConsume(1));
sleep(mocked, 1000);
assertTrue(defaultTokenBucketFullStart.tryConsume(2));
assertFalse(defaultTokenBucketFullStart.tryConsume(1));
}
}
@Test
public void testForStrictTokenBucket() throws InterruptedException {
long unitProduceNum = 5;
long maxTokenNum = 10;
long intervalInMs = 1000;
final int n = 64;
long testStart = System.currentTimeMillis();
setCurrentMillis(testStart);
try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
long unitProduceNum = 5;
long maxTokenNum = 10;
long intervalInMs = 1000;
final int n = 64;
long testStart = System.currentTimeMillis();
setCurrentMillis(mocked, testStart);
final AtomicLong passNum = new AtomicLong();
final AtomicLong passNumFullStart = new AtomicLong();
final CountDownLatch countDownLatch = new CountDownLatch(n);
final CountDownLatch countDownLatchFullStart = new CountDownLatch(n);
final StrictTokenBucket strictTokenBucket = new StrictTokenBucket(unitProduceNum, maxTokenNum, intervalInMs);
final StrictTokenBucket strictTokenBucketFullStart = new StrictTokenBucket(unitProduceNum, maxTokenNum, true,
intervalInMs);
final AtomicLong passNum = new AtomicLong();
final AtomicLong passNumFullStart = new AtomicLong();
final CountDownLatch countDownLatch = new CountDownLatch(n);
final CountDownLatch countDownLatchFullStart = new CountDownLatch(n);
final StrictTokenBucket strictTokenBucket = new StrictTokenBucket(unitProduceNum, maxTokenNum, intervalInMs);
final StrictTokenBucket strictTokenBucketFullStart = new StrictTokenBucket(unitProduceNum, maxTokenNum, true,
intervalInMs);
for (int i = 0; i < n; i++) {
threadPoolExecutor.execute(new Runnable() {
@Override
public void run() {
if (strictTokenBucket.tryConsume(1)) {
passNum.incrementAndGet();
for (int i = 0; i < n; i++) {
threadPoolExecutor.execute(new Runnable() {
@Override
public void run() {
if (strictTokenBucket.tryConsume(1)) {
passNum.incrementAndGet();
}
countDownLatch.countDown();
}
countDownLatch.countDown();
}
});
threadPoolExecutor.execute(new Runnable() {
@Override
public void run() {
if (strictTokenBucketFullStart.tryConsume(1)) {
passNumFullStart.incrementAndGet();
});
threadPoolExecutor.execute(new Runnable() {
@Override
public void run() {
if (strictTokenBucketFullStart.tryConsume(1)) {
passNumFullStart.incrementAndGet();
}
countDownLatchFullStart.countDown();
}
countDownLatchFullStart.countDown();
}
});
});
}
countDownLatch.await();
countDownLatchFullStart.await();
assertEquals(5, passNum.longValue());
assertEquals(10, passNumFullStart.longValue());
}
countDownLatch.await();
countDownLatchFullStart.await();
assertEquals(5, passNum.longValue());
assertEquals(10, passNumFullStart.longValue());
}
}

View File

@ -17,9 +17,11 @@ package com.alibaba.csp.sentinel.slots.statistic.base;
import java.util.concurrent.atomic.AtomicInteger;
import com.alibaba.csp.sentinel.util.TimeUtil;
import org.junit.Test;
import com.alibaba.csp.sentinel.test.AbstractTimeBasedTest;
import org.mockito.MockedStatic;
import static org.junit.Assert.*;
@ -30,36 +32,38 @@ public class LeapArrayTest extends AbstractTimeBasedTest {
@Test
public void testGetValidHead() {
int windowLengthInMs = 100;
int intervalInMs = 1000;
int sampleCount = intervalInMs / windowLengthInMs;
LeapArray<AtomicInteger> leapArray = new LeapArray<AtomicInteger>(sampleCount, intervalInMs) {
@Override
public AtomicInteger newEmptyBucket(long time) {
return new AtomicInteger(0);
try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
int windowLengthInMs = 100;
int intervalInMs = 1000;
int sampleCount = intervalInMs / windowLengthInMs;
LeapArray<AtomicInteger> leapArray = new LeapArray<AtomicInteger>(sampleCount, intervalInMs) {
@Override
public AtomicInteger newEmptyBucket(long time) {
return new AtomicInteger(0);
}
@Override
protected WindowWrap<AtomicInteger> resetWindowTo(WindowWrap<AtomicInteger> windowWrap, long startTime) {
windowWrap.resetTo(startTime);
windowWrap.value().set(0);
return windowWrap;
}
};
WindowWrap<AtomicInteger> expected1 = leapArray.currentWindow();
expected1.value().addAndGet(1);
sleep(mocked, windowLengthInMs);
WindowWrap<AtomicInteger> expected2 = leapArray.currentWindow();
expected2.value().addAndGet(2);
for (int i = 0; i < sampleCount - 2; i++) {
sleep(mocked, windowLengthInMs);
leapArray.currentWindow().value().addAndGet(i + 3);
}
@Override
protected WindowWrap<AtomicInteger> resetWindowTo(WindowWrap<AtomicInteger> windowWrap, long startTime) {
windowWrap.resetTo(startTime);
windowWrap.value().set(0);
return windowWrap;
}
};
WindowWrap<AtomicInteger> expected1 = leapArray.currentWindow();
expected1.value().addAndGet(1);
sleep(windowLengthInMs);
WindowWrap<AtomicInteger> expected2 = leapArray.currentWindow();
expected2.value().addAndGet(2);
for (int i = 0; i < sampleCount - 2; i++) {
sleep(windowLengthInMs);
leapArray.currentWindow().value().addAndGet(i + 3);
assertSame(expected1, leapArray.getValidHead());
sleep(mocked, windowLengthInMs);
assertSame(expected2, leapArray.getValidHead());
}
assertSame(expected1, leapArray.getValidHead());
sleep(windowLengthInMs);
assertSame(expected2, leapArray.getValidHead());
}
}

View File

@ -10,6 +10,7 @@ import com.alibaba.csp.sentinel.test.AbstractTimeBasedTest;
import com.alibaba.csp.sentinel.util.TimeUtil;
import org.junit.Test;
import org.mockito.MockedStatic;
import static org.junit.Assert.assertEquals;
@ -27,113 +28,120 @@ public class OccupiableBucketLeapArrayTest extends AbstractTimeBasedTest {
@Test
public void testNewWindow() {
long currentTime = System.currentTimeMillis();
setCurrentMillis(currentTime);
OccupiableBucketLeapArray leapArray = new OccupiableBucketLeapArray(sampleCount, intervalInMs);
try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
long currentTime = System.currentTimeMillis();
setCurrentMillis(mocked, currentTime);
OccupiableBucketLeapArray leapArray = new OccupiableBucketLeapArray(sampleCount, intervalInMs);
WindowWrap<MetricBucket> currentWindow = leapArray.currentWindow(currentTime);
currentWindow.value().addPass(1);
assertEquals(currentWindow.value().pass(), 1L);
leapArray.addWaiting(currentTime + windowLengthInMs, 1);
assertEquals(leapArray.currentWaiting(), 1);
assertEquals(currentWindow.value().pass(), 1L);
WindowWrap<MetricBucket> currentWindow = leapArray.currentWindow(currentTime);
currentWindow.value().addPass(1);
assertEquals(currentWindow.value().pass(), 1L);
leapArray.addWaiting(currentTime + windowLengthInMs, 1);
assertEquals(leapArray.currentWaiting(), 1);
assertEquals(currentWindow.value().pass(), 1L);
}
}
@Test
public void testWindowInOneInterval() {
OccupiableBucketLeapArray leapArray = new OccupiableBucketLeapArray(sampleCount, intervalInMs);
long currentTime = System.currentTimeMillis();
setCurrentMillis(currentTime);
try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
OccupiableBucketLeapArray leapArray = new OccupiableBucketLeapArray(sampleCount, intervalInMs);
long currentTime = System.currentTimeMillis();
setCurrentMillis(mocked, currentTime);
WindowWrap<MetricBucket> currentWindow = leapArray.currentWindow(currentTime);
currentWindow.value().addPass(1);
assertEquals(currentWindow.value().pass(), 1L);
WindowWrap<MetricBucket> currentWindow = leapArray.currentWindow(currentTime);
currentWindow.value().addPass(1);
assertEquals(currentWindow.value().pass(), 1L);
leapArray.addWaiting(currentTime + windowLengthInMs, 2);
assertEquals(leapArray.currentWaiting(), 2);
assertEquals(currentWindow.value().pass(), 1L);
leapArray.addWaiting(currentTime + windowLengthInMs, 2);
assertEquals(leapArray.currentWaiting(), 2);
assertEquals(currentWindow.value().pass(), 1L);
leapArray.currentWindow(currentTime + windowLengthInMs);
List<MetricBucket> values = leapArray.values(currentTime + windowLengthInMs);
assertEquals(values.size(), 2);
leapArray.currentWindow(currentTime + windowLengthInMs);
List<MetricBucket> values = leapArray.values(currentTime + windowLengthInMs);
assertEquals(values.size(), 2);
long sum = 0;
for (MetricBucket bucket : values) {
sum += bucket.pass();
long sum = 0;
for (MetricBucket bucket : values) {
sum += bucket.pass();
}
assertEquals(sum, 3);
}
assertEquals(sum, 3);
}
@Test
public void testMultiThreadUpdateEmptyWindow() throws Exception {
final long time = System.currentTimeMillis();
setCurrentMillis(time);
final int nThreads = 16;
final OccupiableBucketLeapArray leapArray = new OccupiableBucketLeapArray(sampleCount, intervalInMs);
final CountDownLatch latch = new CountDownLatch(nThreads);
Runnable task = new Runnable() {
@Override
public void run() {
leapArray.currentWindow(time).value().addPass(1);
leapArray.addWaiting(time + windowLengthInMs, 1);
latch.countDown();
try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
final long time = System.currentTimeMillis();
setCurrentMillis(mocked, time);
final int nThreads = 16;
final OccupiableBucketLeapArray leapArray = new OccupiableBucketLeapArray(sampleCount, intervalInMs);
final CountDownLatch latch = new CountDownLatch(nThreads);
Runnable task = new Runnable() {
@Override
public void run() {
leapArray.currentWindow(time).value().addPass(1);
leapArray.addWaiting(time + windowLengthInMs, 1);
latch.countDown();
}
};
for (int i = 0; i < nThreads; i++) {
new Thread(task).start();
}
};
for (int i = 0; i < nThreads; i++) {
new Thread(task).start();
latch.await();
assertEquals(nThreads, leapArray.currentWindow(time).value().pass());
assertEquals(nThreads, leapArray.currentWaiting());
leapArray.currentWindow(time + windowLengthInMs);
long sum = 0;
List<MetricBucket> values = leapArray.values(time + windowLengthInMs);
for (MetricBucket bucket : values) {
sum += bucket.pass();
}
assertEquals(values.size(), 2);
assertEquals(sum, nThreads * 2);
}
latch.await();
assertEquals(nThreads, leapArray.currentWindow(time).value().pass());
assertEquals(nThreads, leapArray.currentWaiting());
leapArray.currentWindow(time + windowLengthInMs);
long sum = 0;
List<MetricBucket> values = leapArray.values(time + windowLengthInMs);
for (MetricBucket bucket : values) {
sum += bucket.pass();
}
assertEquals(values.size(), 2);
assertEquals(sum, nThreads * 2);
}
@Test
public void testWindowAfterOneInterval() {
OccupiableBucketLeapArray leapArray = new OccupiableBucketLeapArray(sampleCount, intervalInMs);
long currentTime = System.currentTimeMillis();
setCurrentMillis(currentTime);
try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
OccupiableBucketLeapArray leapArray = new OccupiableBucketLeapArray(sampleCount, intervalInMs);
long currentTime = System.currentTimeMillis();
setCurrentMillis(mocked, currentTime);
System.out.println(currentTime);
for (int i = 0; i < intervalInSec * 1000 / windowLengthInMs; i++) {
WindowWrap<MetricBucket> currentWindow = leapArray.currentWindow(currentTime + i * windowLengthInMs);
currentWindow.value().addPass(1);
leapArray.addWaiting(currentTime + (i + 1) * windowLengthInMs, 1);
System.out.println(currentTime + i * windowLengthInMs);
leapArray.debug(currentTime + i * windowLengthInMs);
System.out.println(currentTime);
for (int i = 0; i < intervalInSec * 1000 / windowLengthInMs; i++) {
WindowWrap<MetricBucket> currentWindow = leapArray.currentWindow(currentTime + i * windowLengthInMs);
currentWindow.value().addPass(1);
leapArray.addWaiting(currentTime + (i + 1) * windowLengthInMs, 1);
System.out.println(currentTime + i * windowLengthInMs);
leapArray.debug(currentTime + i * windowLengthInMs);
}
System.out.println(currentTime + intervalInSec * 1000);
List<MetricBucket> values = leapArray
.values(currentTime - currentTime % windowLengthInMs + intervalInSec * 1000);
leapArray.debug(currentTime + intervalInSec * 1000);
assertEquals(values.size(), intervalInSec * 1000 / windowLengthInMs);
long sum = 0;
for (MetricBucket bucket : values) {
sum += bucket.pass();
}
assertEquals(sum, 2 * intervalInSec * 1000 / windowLengthInMs - 1);
/**
* https://github.com/alibaba/Sentinel/issues/685
*
* Here we could not use exactly current time, because the following result is related with the above elapse.
* So we use the beginning current time to ensure.
*/
assertEquals(leapArray.currentWaiting(), 10);
}
System.out.println(currentTime + intervalInSec * 1000);
List<MetricBucket> values = leapArray
.values(currentTime - currentTime % windowLengthInMs + intervalInSec * 1000);
leapArray.debug(currentTime + intervalInSec * 1000);
assertEquals(values.size(), intervalInSec * 1000 / windowLengthInMs);
long sum = 0;
for (MetricBucket bucket : values) {
sum += bucket.pass();
}
assertEquals(sum, 2 * intervalInSec * 1000 / windowLengthInMs - 1);
/**
* https://github.com/alibaba/Sentinel/issues/685
*
* Here we could not use exactly current time, because the following result is related with the above elapse.
* So we use the beginning current time to ensure.
*/
assertEquals(leapArray.currentWaiting(), 10);
}
}

View File

@ -15,58 +15,58 @@
*/
package com.alibaba.csp.sentinel.test;
import java.util.concurrent.ThreadLocalRandom;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.Tracer;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.junit.runner.RunWith;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import com.alibaba.csp.sentinel.util.TimeUtil;
import java.util.concurrent.ThreadLocalRandom;
/**
* Mock support for {@link TimeUtil}.
*
* @author jason
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({ TimeUtil.class })
@RunWith(MockitoJUnitRunner.class)
public abstract class AbstractTimeBasedTest {
private long currentMillis = 0;
{
PowerMockito.mockStatic(TimeUtil.class);
PowerMockito.when(TimeUtil.currentTimeMillis()).thenReturn(currentMillis);
public MockedStatic<TimeUtil> mockTimeUtil() {
MockedStatic<TimeUtil> mocked = Mockito.mockStatic(TimeUtil.class);
mocked.when(TimeUtil::currentTimeMillis).thenReturn(currentMillis);
return mocked;
}
protected final void useActualTime() {
PowerMockito.when(TimeUtil.currentTimeMillis()).thenCallRealMethod();
protected final void useActualTime(MockedStatic<TimeUtil> mocked) {
mocked.when(TimeUtil::currentTimeMillis).thenCallRealMethod();
}
protected final void setCurrentMillis(long cur) {
protected final void setCurrentMillis(MockedStatic<TimeUtil> mocked, long cur) {
currentMillis = cur;
PowerMockito.when(TimeUtil.currentTimeMillis()).thenReturn(currentMillis);
mocked.when(TimeUtil::currentTimeMillis).thenReturn(currentMillis);
}
protected final void sleep(int t) {
protected final void sleep(MockedStatic<TimeUtil> mocked, long t) {
currentMillis += t;
PowerMockito.when(TimeUtil.currentTimeMillis()).thenReturn(currentMillis);
mocked.when(TimeUtil::currentTimeMillis).thenReturn(currentMillis);
}
protected final void sleepSecond(int timeSec) {
sleep(timeSec * 1000);
protected final void sleepSecond(MockedStatic<TimeUtil> mocked, long timeSec) {
sleep(mocked, timeSec * 1000);
}
protected final boolean entryAndSleepFor(String res, int sleepMs) {
protected final boolean entryAndSleepFor(MockedStatic<TimeUtil> mocked, String res, int sleepMs) {
Entry entry = null;
try {
entry = SphU.entry(res);
sleep(sleepMs);
sleep(mocked, sleepMs);
} catch (BlockException ex) {
return false;
} catch (Exception ex) {
@ -79,14 +79,14 @@ public abstract class AbstractTimeBasedTest {
return true;
}
protected final boolean entryWithErrorIfPresent(String res, Exception ex) {
protected final boolean entryWithErrorIfPresent(MockedStatic<TimeUtil> mocked, String res, Exception ex) {
Entry entry = null;
try {
entry = SphU.entry(res);
if (ex != null) {
Tracer.traceEntry(ex, entry);
}
sleep(ThreadLocalRandom.current().nextInt(5, 10));
sleep(mocked, ThreadLocalRandom.current().nextInt(5, 10));
} catch (BlockException b) {
return false;
} finally {

View File

@ -36,6 +36,7 @@ import static org.assertj.core.api.Assertions.fail;
/**
* @author sea
*/
@Ignore
public class SentinelAnnotationInterceptorIntegrationTest {
static SeContainer container;

View File

@ -12,7 +12,8 @@
<artifactId>sentinel-datasource-eureka</artifactId>
<properties>
<spring.cloud.version>2.1.2.RELEASE</spring.cloud.version>
<spring.boot.version>2.6.1</spring.boot.version>
<spring.cloud.version>3.1.0</spring.cloud.version>
</properties>
@ -27,6 +28,12 @@
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
@ -42,7 +49,7 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring.cloud.version}</version>
<version>${spring.boot.version}</version>
<scope>test</scope>
</dependency>

View File

@ -13,7 +13,8 @@
<packaging>jar</packaging>
<properties>
<spring.cloud.version>2.0.0.RELEASE</spring.cloud.version>
<spring.boot.version>2.1.3.RELEASE</spring.boot.version>
<spring.cloud.version>2.1.9.RELEASE</spring.cloud.version>
</properties>
<dependencies>
@ -44,7 +45,7 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring.cloud.version}</version>
<version>${spring.boot.version}</version>
<scope>test</scope>
</dependency>
@ -58,7 +59,7 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring.cloud.version}</version>
<version>${spring.boot.version}</version>
<scope>test</scope>
</dependency>

View File

@ -36,17 +36,7 @@
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<artifactId>mockito-inline</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

View File

@ -0,0 +1,58 @@
/*
* 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.csp.sentinel.block.flow.param;
import org.junit.runner.RunWith;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import com.alibaba.csp.sentinel.util.TimeUtil;
/**
* Mock support for {@link TimeUtil}.
*
* @author jason
*/
@RunWith(MockitoJUnitRunner.class)
public abstract class AbstractTimeBasedTest {
private long currentMillis = 0;
public MockedStatic<TimeUtil> mockTimeUtil() {
MockedStatic<TimeUtil> mocked = Mockito.mockStatic(TimeUtil.class);
mocked.when(TimeUtil::currentTimeMillis).thenReturn(currentMillis);
return mocked;
}
protected final void useActualTime(MockedStatic<TimeUtil> mocked) {
mocked.when(TimeUtil::currentTimeMillis).thenCallRealMethod();
}
protected final void setCurrentMillis(MockedStatic<TimeUtil> mocked, long cur) {
currentMillis = cur;
mocked.when(TimeUtil::currentTimeMillis).thenReturn(currentMillis);
}
protected final void sleep(MockedStatic<TimeUtil> mocked, long t) {
currentMillis += t;
mocked.when(TimeUtil::currentTimeMillis).thenReturn(currentMillis);
}
protected final void sleepSecond(MockedStatic<TimeUtil> mocked, long timeSec) {
sleep(mocked, timeSec * 1000);
}
}

View File

@ -33,8 +33,9 @@ import com.alibaba.csp.sentinel.EntryType;
import com.alibaba.csp.sentinel.slotchain.ResourceWrapper;
import com.alibaba.csp.sentinel.slotchain.StringResourceWrapper;
import com.alibaba.csp.sentinel.slots.statistic.cache.ConcurrentLinkedHashMapWrapper;
import com.alibaba.csp.sentinel.test.AbstractTimeBasedTest;
import com.alibaba.csp.sentinel.block.flow.param.AbstractTimeBasedTest;
import com.alibaba.csp.sentinel.util.TimeUtil;
import org.mockito.MockedStatic;
/**
* @author jialiang.linjl
@ -44,283 +45,293 @@ public class ParamFlowDefaultCheckerTest extends AbstractTimeBasedTest {
@Test
public void testCheckQpsWithLongIntervalAndHighThreshold() {
// This test case is intended to avoid number overflow.
final String resourceName = "testCheckQpsWithLongIntervalAndHighThreshold";
final ResourceWrapper resourceWrapper = new StringResourceWrapper(resourceName, EntryType.IN);
int paramIdx = 0;
try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
// This test case is intended to avoid number overflow.
final String resourceName = "testCheckQpsWithLongIntervalAndHighThreshold";
final ResourceWrapper resourceWrapper = new StringResourceWrapper(resourceName, EntryType.IN);
int paramIdx = 0;
// Set a large threshold.
long threshold = 25000L;
// Set a large threshold.
long threshold = 25000L;
ParamFlowRule rule = new ParamFlowRule(resourceName)
.setCount(threshold)
.setParamIdx(paramIdx);
ParamFlowRule rule = new ParamFlowRule(resourceName)
.setCount(threshold)
.setParamIdx(paramIdx);
String valueA = "valueA";
ParameterMetric metric = new ParameterMetric();
ParameterMetricStorage.getMetricsMap().put(resourceWrapper.getName(), metric);
metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
metric.getRuleTokenCounterMap().put(rule,
new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
String valueA = "valueA";
ParameterMetric metric = new ParameterMetric();
ParameterMetricStorage.getMetricsMap().put(resourceWrapper.getName(), metric);
metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
metric.getRuleTokenCounterMap().put(rule,
new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
// We mock the time directly to avoid unstable behaviour.
setCurrentMillis(System.currentTimeMillis());
// We mock the time directly to avoid unstable behaviour.
setCurrentMillis(mocked, System.currentTimeMillis());
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
// 24 hours passed.
// This can make `toAddCount` larger that Integer.MAX_VALUE.
sleep(1000 * 60 * 60 * 24);
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
// 24 hours passed.
// This can make `toAddCount` larger that Integer.MAX_VALUE.
sleep(mocked, 1000 * 60 * 60 * 24);
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
// 48 hours passed.
sleep(1000 * 60 * 60 * 48);
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
// 48 hours passed.
sleep(mocked, 1000 * 60 * 60 * 48);
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
}
}
@Test
public void testParamFlowDefaultCheckSingleQps() {
final String resourceName = "testParamFlowDefaultCheckSingleQps";
final ResourceWrapper resourceWrapper = new StringResourceWrapper(resourceName, EntryType.IN);
int paramIdx = 0;
try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
final String resourceName = "testParamFlowDefaultCheckSingleQps";
final ResourceWrapper resourceWrapper = new StringResourceWrapper(resourceName, EntryType.IN);
int paramIdx = 0;
long threshold = 5L;
long threshold = 5L;
ParamFlowRule rule = new ParamFlowRule();
rule.setResource(resourceName);
rule.setCount(threshold);
rule.setParamIdx(paramIdx);
ParamFlowRule rule = new ParamFlowRule();
rule.setResource(resourceName);
rule.setCount(threshold);
rule.setParamIdx(paramIdx);
String valueA = "valueA";
ParameterMetric metric = new ParameterMetric();
ParameterMetricStorage.getMetricsMap().put(resourceWrapper.getName(), metric);
metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
metric.getRuleTokenCounterMap().put(rule,
new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
String valueA = "valueA";
ParameterMetric metric = new ParameterMetric();
ParameterMetricStorage.getMetricsMap().put(resourceWrapper.getName(), metric);
metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
metric.getRuleTokenCounterMap().put(rule,
new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
// We mock the time directly to avoid unstable behaviour.
setCurrentMillis(System.currentTimeMillis());
// We mock the time directly to avoid unstable behaviour.
setCurrentMillis(mocked, System.currentTimeMillis());
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertFalse(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertFalse(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
sleep(3000);
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertFalse(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
sleep(mocked, 3000);
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertFalse(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
}
}
@Test
public void testParamFlowDefaultCheckSingleQpsWithBurst() throws InterruptedException {
final String resourceName = "testParamFlowDefaultCheckSingleQpsWithBurst";
final ResourceWrapper resourceWrapper = new StringResourceWrapper(resourceName, EntryType.IN);
int paramIdx = 0;
try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
final String resourceName = "testParamFlowDefaultCheckSingleQpsWithBurst";
final ResourceWrapper resourceWrapper = new StringResourceWrapper(resourceName, EntryType.IN);
int paramIdx = 0;
long threshold = 5L;
long threshold = 5L;
ParamFlowRule rule = new ParamFlowRule();
rule.setResource(resourceName);
rule.setCount(threshold);
rule.setParamIdx(paramIdx);
rule.setBurstCount(3);
ParamFlowRule rule = new ParamFlowRule();
rule.setResource(resourceName);
rule.setCount(threshold);
rule.setParamIdx(paramIdx);
rule.setBurstCount(3);
String valueA = "valueA";
ParameterMetric metric = new ParameterMetric();
ParameterMetricStorage.getMetricsMap().put(resourceWrapper.getName(), metric);
metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
metric.getRuleTokenCounterMap().put(rule,
new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
String valueA = "valueA";
ParameterMetric metric = new ParameterMetric();
ParameterMetricStorage.getMetricsMap().put(resourceWrapper.getName(), metric);
metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
metric.getRuleTokenCounterMap().put(rule,
new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
// We mock the time directly to avoid unstable behaviour.
setCurrentMillis(System.currentTimeMillis());
// We mock the time directly to avoid unstable behaviour.
setCurrentMillis(mocked, System.currentTimeMillis());
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertFalse(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertFalse(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
sleep(1002);
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertFalse(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
sleep(mocked, 1002);
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertFalse(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
sleep(1002);
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertFalse(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
sleep(mocked, 1002);
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertFalse(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
sleep(2000);
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertFalse(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
sleep(mocked, 2000);
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertFalse(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
sleep(1002);
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertFalse(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
sleep(mocked, 1002);
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertFalse(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
}
}
@Test
public void testParamFlowDefaultCheckQpsInDifferentDuration() throws InterruptedException {
final String resourceName = "testParamFlowDefaultCheckQpsInDifferentDuration";
final ResourceWrapper resourceWrapper = new StringResourceWrapper(resourceName, EntryType.IN);
int paramIdx = 0;
try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
final String resourceName = "testParamFlowDefaultCheckQpsInDifferentDuration";
final ResourceWrapper resourceWrapper = new StringResourceWrapper(resourceName, EntryType.IN);
int paramIdx = 0;
long threshold = 5L;
long threshold = 5L;
ParamFlowRule rule = new ParamFlowRule();
rule.setResource(resourceName);
rule.setCount(threshold);
rule.setParamIdx(paramIdx);
rule.setDurationInSec(60);
ParamFlowRule rule = new ParamFlowRule();
rule.setResource(resourceName);
rule.setCount(threshold);
rule.setParamIdx(paramIdx);
rule.setDurationInSec(60);
String valueA = "helloWorld";
ParameterMetric metric = new ParameterMetric();
ParameterMetricStorage.getMetricsMap().put(resourceWrapper.getName(), metric);
metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
metric.getRuleTokenCounterMap().put(rule,
new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
String valueA = "helloWorld";
ParameterMetric metric = new ParameterMetric();
ParameterMetricStorage.getMetricsMap().put(resourceWrapper.getName(), metric);
metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
metric.getRuleTokenCounterMap().put(rule,
new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
// We mock the time directly to avoid unstable behaviour.
setCurrentMillis(System.currentTimeMillis());
// We mock the time directly to avoid unstable behaviour.
setCurrentMillis(mocked, System.currentTimeMillis());
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertFalse(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertFalse(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
sleepSecond(1);
assertFalse(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
sleepSecond(mocked, 1);
assertFalse(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
sleepSecond(10);
assertFalse(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
sleepSecond(mocked, 10);
assertFalse(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
sleepSecond(30);
assertFalse(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
sleepSecond(mocked, 30);
assertFalse(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
sleepSecond(30);
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
sleepSecond(mocked, 30);
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertTrue(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertFalse(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
assertFalse(ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA));
}
}
@Test
public void testParamFlowDefaultCheckSingleValueCheckQpsMultipleThreads() throws Exception {
// In this test case we use the actual time.
useActualTime();
try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
// In this test case we use the actual time.
useActualTime(mocked);
final String resourceName = "testParamFlowDefaultCheckSingleValueCheckQpsMultipleThreads";
final ResourceWrapper resourceWrapper = new StringResourceWrapper(resourceName, EntryType.IN);
int paramIdx = 0;
final String resourceName = "testParamFlowDefaultCheckSingleValueCheckQpsMultipleThreads";
final ResourceWrapper resourceWrapper = new StringResourceWrapper(resourceName, EntryType.IN);
int paramIdx = 0;
long threshold = 5L;
long threshold = 5L;
final ParamFlowRule rule = new ParamFlowRule();
rule.setResource(resourceName);
rule.setCount(threshold);
rule.setParamIdx(paramIdx);
final ParamFlowRule rule = new ParamFlowRule();
rule.setResource(resourceName);
rule.setCount(threshold);
rule.setParamIdx(paramIdx);
final String valueA = "valueA";
ParameterMetric metric = new ParameterMetric();
ParameterMetricStorage.getMetricsMap().put(resourceWrapper.getName(), metric);
metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
metric.getRuleTokenCounterMap().put(rule,
new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
int threadCount = 40;
final String valueA = "valueA";
ParameterMetric metric = new ParameterMetric();
ParameterMetricStorage.getMetricsMap().put(resourceWrapper.getName(), metric);
metric.getRuleTimeCounterMap().put(rule, new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
metric.getRuleTokenCounterMap().put(rule,
new ConcurrentLinkedHashMapWrapper<Object, AtomicLong>(4000));
int threadCount = 40;
final CountDownLatch waitLatch = new CountDownLatch(threadCount);
final AtomicInteger successCount = new AtomicInteger();
for (int i = 0; i < threadCount; i++) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
if (ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA)) {
successCount.incrementAndGet();
}
waitLatch.countDown();
}
});
t.setName("sentinel-simulate-traffic-task-" + i);
t.start();
}
waitLatch.await();
assertEquals(successCount.get(), threshold);
successCount.set(0);
System.out.println("testParamFlowDefaultCheckSingleValueCheckQpsMultipleThreads: sleep for 3 seconds");
TimeUnit.SECONDS.sleep(3);
successCount.set(0);
final CountDownLatch waitLatch1 = new CountDownLatch(threadCount);
final long currentTime = TimeUtil.currentTimeMillis();
final long endTime = currentTime + rule.getDurationInSec() * 1000 - 1;
for (int i = 0; i < threadCount; i++) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
long currentTime1 = currentTime;
while (currentTime1 <= endTime) {
final CountDownLatch waitLatch = new CountDownLatch(threadCount);
final AtomicInteger successCount = new AtomicInteger();
for (int i = 0; i < threadCount; i++) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
if (ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA)) {
successCount.incrementAndGet();
}
try {
TimeUnit.MILLISECONDS.sleep(ThreadLocalRandom.current().nextInt(20));
} catch (InterruptedException e) {
e.printStackTrace();
}
currentTime1 = TimeUtil.currentTimeMillis();
waitLatch.countDown();
}
waitLatch1.countDown();
}
});
t.setName("sentinel-simulate-traffic-task-" + i);
t.start();
}
waitLatch.await();
});
t.setName("sentinel-simulate-traffic-task-" + i);
t.start();
assertEquals(successCount.get(), threshold);
successCount.set(0);
System.out.println("testParamFlowDefaultCheckSingleValueCheckQpsMultipleThreads: sleep for 3 seconds");
TimeUnit.SECONDS.sleep(3);
successCount.set(0);
final CountDownLatch waitLatch1 = new CountDownLatch(threadCount);
final long currentTime = TimeUtil.currentTimeMillis();
final long endTime = currentTime + rule.getDurationInSec() * 1000 - 1;
for (int i = 0; i < threadCount; i++) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
long currentTime1 = currentTime;
while (currentTime1 <= endTime) {
if (ParamFlowChecker.passSingleValueCheck(resourceWrapper, rule, 1, valueA)) {
successCount.incrementAndGet();
}
try {
TimeUnit.MILLISECONDS.sleep(ThreadLocalRandom.current().nextInt(20));
} catch (InterruptedException e) {
e.printStackTrace();
}
currentTime1 = TimeUtil.currentTimeMillis();
}
waitLatch1.countDown();
}
});
t.setName("sentinel-simulate-traffic-task-" + i);
t.start();
}
waitLatch1.await();
assertEquals(successCount.get(), threshold);
}
waitLatch1.await();
assertEquals(successCount.get(), threshold);
}
@Before

View File

@ -1,58 +0,0 @@
/*
* 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.csp.sentinel.test;
import com.alibaba.csp.sentinel.util.TimeUtil;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
/**
* Mock support for {@link TimeUtil}
*
* @author jason
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({TimeUtil.class})
public abstract class AbstractTimeBasedTest {
private long currentMillis = 0;
{
PowerMockito.mockStatic(TimeUtil.class);
PowerMockito.when(TimeUtil.currentTimeMillis()).thenReturn(currentMillis);
}
protected final void useActualTime() {
PowerMockito.when(TimeUtil.currentTimeMillis()).thenCallRealMethod();
}
protected final void setCurrentMillis(long cur) {
currentMillis = cur;
PowerMockito.when(TimeUtil.currentTimeMillis()).thenReturn(currentMillis);
}
protected final void sleep(int t) {
currentMillis += t;
PowerMockito.when(TimeUtil.currentTimeMillis()).thenReturn(currentMillis);
}
protected final void sleepSecond(int timeSec) {
sleep(timeSec * 1000);
}
}