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 version: 2
jobs: 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: document-lint:
docker: docker:
# this image is build from Dockerfile # this image is build from Dockerfile
@ -49,5 +38,4 @@ workflows:
version: 2 version: 2
ci: ci:
jobs: jobs:
- integration-test
- document-lint - document-lint

View File

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

View File

@ -34,7 +34,7 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v3 uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - 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 # 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 # 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). # 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) # 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 --> <!-- Test libs -->
<junit.version>4.12</junit.version> <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> <assertj.version>3.12.1</assertj.version>
<awaitility.version>3.1.5</awaitility.version> <awaitility.version>3.1.5</awaitility.version>
<powermock.version>2.0.0</powermock.version> <powermock.version>2.0.0</powermock.version>
@ -56,14 +56,14 @@
<java.source.version>1.8</java.source.version> <java.source.version>1.8</java.source.version>
<java.target.version>1.8</java.target.version> <java.target.version>1.8</java.target.version>
<java.encoding>UTF-8</java.encoding> <java.encoding>UTF-8</java.encoding>
<maven.compiler.version>3.8.0</maven.compiler.version> <maven.compiler.version>3.12.0</maven.compiler.version>
<maven.surefire.version>2.22.1</maven.surefire.version> <maven.surefire.version>3.2.5</maven.surefire.version>
<maven.source.version>3.0.1</maven.source.version> <maven.source.version>3.0.1</maven.source.version>
<maven.javadoc.version>3.0.1</maven.javadoc.version> <maven.javadoc.version>3.0.1</maven.javadoc.version>
<maven.deploy.version>2.8.2</maven.deploy.version> <maven.deploy.version>2.8.2</maven.deploy.version>
<maven.gpg.version>1.6</maven.gpg.version> <maven.gpg.version>1.6</maven.gpg.version>
<maven.jacoco.version>0.8.3</maven.jacoco.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> <maven.pmd.version>3.8</maven.pmd.version>
</properties> </properties>
@ -189,6 +189,12 @@
<version>${mockito.version}</version> <version>${mockito.version}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.assertj</groupId> <groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId> <artifactId>assertj-core</artifactId>
@ -207,18 +213,6 @@
<version>2.0.0.0</version> <version>2.0.0.0</version>
<scope>test</scope> <scope>test</scope>
</dependency> </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> </dependencies>
</dependencyManagement> </dependencyManagement>
@ -271,15 +265,33 @@
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.version}</version> <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> <configuration>
<source>${java.source.version}</source> <release>8</release>
<target>${java.target.version}</target>
<encoding>${java.encoding}</encoding>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<version>${maven.surefire.version}</version>
<configuration> <configuration>
<!-- CircleCI build workaround --> <!-- CircleCI build workaround -->
<argLine>@{argLine} -Xms1024m -Xmx2048m</argLine> <argLine>@{argLine} -Xms1024m -Xmx2048m</argLine>
@ -394,6 +406,30 @@
</repository> </repository>
</distributionManagement> </distributionManagement>
</profile> </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> </profiles>
</project> </project>

View File

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

View File

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

View File

@ -41,16 +41,6 @@
<artifactId>sentinel-datasource-nacos</artifactId> <artifactId>sentinel-datasource-nacos</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </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> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
@ -58,7 +48,7 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.mockito</groupId> <groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId> <artifactId>mockito-inline</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<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.CurrentConcurrencyManager;
import com.alibaba.csp.sentinel.cluster.flow.statistic.concurrent.TokenCacheNodeManager; 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.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.ClusterRuleConstant;
import com.alibaba.csp.sentinel.slots.block.RuleConstant; 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.ClusterFlowConfig;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; 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.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.mockito.MockedStatic;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
@ -60,56 +62,60 @@ public class ConcurrentClusterFlowCheckerTest extends AbstractTimeBasedTest {
@Test @Test
public void testEasyAcquireAndRelease() throws InterruptedException { public void testEasyAcquireAndRelease() throws InterruptedException {
setCurrentMillis(System.currentTimeMillis()); try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
FlowRule rule = ClusterFlowRuleManager.getFlowRuleById(111L); setCurrentMillis(mocked, System.currentTimeMillis());
ArrayList<Long> list = new ArrayList<>(); FlowRule rule = ClusterFlowRuleManager.getFlowRuleById(111L);
for (int i = 0; i < 10; i++) { ArrayList<Long> list = new ArrayList<>();
TokenResult result = ConcurrentClusterFlowChecker.acquireConcurrentToken("127.0.0.1", rule, 1); for (int i = 0; i < 10; i++) {
Assert.assertTrue("fail to acquire token", TokenResult result = ConcurrentClusterFlowChecker.acquireConcurrentToken("127.0.0.1", rule, 1);
result.getStatus() == TokenResultStatus.OK && result.getTokenId() != 0); Assert.assertTrue("fail to acquire token",
list.add(result.getTokenId()); 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); for (int i = 0; i < 10; i++) {
Assert.assertTrue("fail to acquire block token", TokenResult result = ConcurrentClusterFlowChecker.acquireConcurrentToken("127.0.0.1", rule, 1);
result.getStatus() == TokenResultStatus.BLOCKED); 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)); 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", 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 @Test
public void testConcurrentAcquireAndRelease() throws InterruptedException { public void testConcurrentAcquireAndRelease() throws InterruptedException {
setCurrentMillis(System.currentTimeMillis()); try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
final FlowRule rule = ClusterFlowRuleManager.getFlowRuleById(111L); setCurrentMillis(mocked, System.currentTimeMillis());
final CountDownLatch countDownLatch = new CountDownLatch(1000); final FlowRule rule = ClusterFlowRuleManager.getFlowRuleById(111L);
ExecutorService pool = Executors.newFixedThreadPool(100); final CountDownLatch countDownLatch = new CountDownLatch(1000);
ExecutorService pool = Executors.newFixedThreadPool(100);
for (long i = 0; i < 1000; i++) { for (long i = 0; i < 1000; i++) {
Runnable task = new Runnable() { Runnable task = new Runnable() {
@Override @Override
public void run() { public void run() {
assert rule != null; assert rule != null;
TokenResult result = ConcurrentClusterFlowChecker.acquireConcurrentToken("127.0.0.1", rule, 1); TokenResult result = ConcurrentClusterFlowChecker.acquireConcurrentToken("127.0.0.1", rule, 1);
Assert.assertTrue("concurrent control fail", CurrentConcurrencyManager.get(111L).get() <= rule.getCount()); Assert.assertTrue("concurrent control fail", CurrentConcurrencyManager.get(111L).get() <= rule.getCount());
if (result.getStatus() == TokenResultStatus.OK) { if (result.getStatus() == TokenResultStatus.OK) {
ConcurrentClusterFlowChecker.releaseConcurrentToken(result.getTokenId()); 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 @Test

View File

@ -16,16 +16,16 @@
package com.alibaba.csp.sentinel.cluster.flow.statistic.concurrent; 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.rule.ClusterFlowRuleManager;
import com.alibaba.csp.sentinel.cluster.flow.statistic.concurrent.TokenCacheNode; import com.alibaba.csp.sentinel.cluster.server.AbstractTimeBasedTest;
import com.alibaba.csp.sentinel.cluster.flow.statistic.concurrent.TokenCacheNodeManager;
import com.alibaba.csp.sentinel.slots.block.ClusterRuleConstant; import com.alibaba.csp.sentinel.slots.block.ClusterRuleConstant;
import com.alibaba.csp.sentinel.slots.block.RuleConstant; 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.ClusterFlowConfig;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; 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.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.mockito.MockedStatic;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -52,28 +52,30 @@ public class TokenCacheNodeManagerTest extends AbstractTimeBasedTest {
@Test @Test
public void testPutTokenCacheNode() throws InterruptedException { 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++) { for (long i = 0; i < 100; i++) {
final TokenCacheNode node = new TokenCacheNode(); final TokenCacheNode node = new TokenCacheNode();
node.setTokenId(i); node.setTokenId(i);
node.setFlowId(111L); node.setFlowId(111L);
node.setResourceTimeout(10000L); node.setResourceTimeout(10000L);
node.setClientTimeout(10000L); node.setClientTimeout(10000L);
node.setClientAddress("localhost"); node.setClientAddress("localhost");
if (TokenCacheNodeManager.validToken(node)) { if (TokenCacheNodeManager.validToken(node)) {
TokenCacheNodeManager.putTokenCacheNode(node.getTokenId(), 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; package com.alibaba.csp.sentinel.cluster.flow.statistic.limit;
import com.alibaba.csp.sentinel.cluster.server.config.ClusterServerConfigManager; 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.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.mockito.MockedStatic;
public class GlobalRequestLimiterTest extends AbstractTimeBasedTest { public class GlobalRequestLimiterTest extends AbstractTimeBasedTest {
@Before @Before
@ -29,21 +31,23 @@ public class GlobalRequestLimiterTest extends AbstractTimeBasedTest {
@Test @Test
public void testPass() throws InterruptedException { public void testPass() throws InterruptedException {
setCurrentMillis(System.currentTimeMillis()); try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
GlobalRequestLimiter.initIfAbsent("user"); setCurrentMillis(mocked, System.currentTimeMillis());
Assert.assertNotNull(GlobalRequestLimiter.getRequestLimiter("user")); GlobalRequestLimiter.initIfAbsent("user");
Assert.assertEquals(3, GlobalRequestLimiter.getMaxAllowedQps("user"), 0.01); Assert.assertNotNull(GlobalRequestLimiter.getRequestLimiter("user"));
Assert.assertTrue(GlobalRequestLimiter.tryPass("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.assertTrue(GlobalRequestLimiter.tryPass("user"));
Assert.assertFalse(GlobalRequestLimiter.tryPass("user")); Assert.assertTrue(GlobalRequestLimiter.tryPass("user"));
Assert.assertEquals(3, GlobalRequestLimiter.getCurrentQps("user"), 0.01); Assert.assertFalse(GlobalRequestLimiter.tryPass("user"));
Assert.assertEquals(3, GlobalRequestLimiter.getCurrentQps("user"), 0.01);
// wait a second to refresh the window // wait a second to refresh the window
sleep(1000); sleep(mocked, 1000);
Assert.assertTrue(GlobalRequestLimiter.tryPass("user")); Assert.assertTrue(GlobalRequestLimiter.tryPass("user"));
Assert.assertTrue(GlobalRequestLimiter.tryPass("user")); Assert.assertTrue(GlobalRequestLimiter.tryPass("user"));
Assert.assertEquals(2, GlobalRequestLimiter.getCurrentQps("user"), 0.01); Assert.assertEquals(2, GlobalRequestLimiter.getCurrentQps("user"), 0.01);
}
} }
@Test @Test

View File

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

View File

@ -16,31 +16,35 @@
package com.alibaba.csp.sentinel.cluster.flow.statistic.metric; 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.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.Assert;
import org.junit.Test; import org.junit.Test;
import org.mockito.MockedStatic;
public class ClusterMetricTest extends AbstractTimeBasedTest { public class ClusterMetricTest extends AbstractTimeBasedTest {
@Test @Test
public void testTryOccupyNext() { public void testTryOccupyNext() {
setCurrentMillis(System.currentTimeMillis()); try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
ClusterMetric metric = new ClusterMetric(5, 25); setCurrentMillis(mocked, System.currentTimeMillis());
metric.add(ClusterFlowEvent.PASS, 1); ClusterMetric metric = new ClusterMetric(5, 25);
metric.add(ClusterFlowEvent.PASS, 2); metric.add(ClusterFlowEvent.PASS, 1);
metric.add(ClusterFlowEvent.PASS, 1); metric.add(ClusterFlowEvent.PASS, 2);
metric.add(ClusterFlowEvent.BLOCK, 1); metric.add(ClusterFlowEvent.PASS, 1);
Assert.assertEquals(4, metric.getSum(ClusterFlowEvent.PASS)); metric.add(ClusterFlowEvent.BLOCK, 1);
Assert.assertEquals(1, metric.getSum(ClusterFlowEvent.BLOCK)); Assert.assertEquals(4, metric.getSum(ClusterFlowEvent.PASS));
Assert.assertEquals(160, metric.getAvg(ClusterFlowEvent.PASS), 0.01); Assert.assertEquals(1, metric.getSum(ClusterFlowEvent.BLOCK));
Assert.assertEquals(200, metric.tryOccupyNext(ClusterFlowEvent.PASS, 111, 900)); Assert.assertEquals(160, metric.getAvg(ClusterFlowEvent.PASS), 0.01);
metric.add(ClusterFlowEvent.PASS, 1); Assert.assertEquals(200, metric.tryOccupyNext(ClusterFlowEvent.PASS, 111, 900));
metric.add(ClusterFlowEvent.PASS, 2); metric.add(ClusterFlowEvent.PASS, 1);
metric.add(ClusterFlowEvent.PASS, 1); metric.add(ClusterFlowEvent.PASS, 2);
Assert.assertEquals(200, metric.tryOccupyNext(ClusterFlowEvent.PASS, 222, 900)); metric.add(ClusterFlowEvent.PASS, 1);
metric.add(ClusterFlowEvent.PASS, 1); Assert.assertEquals(200, metric.tryOccupyNext(ClusterFlowEvent.PASS, 222, 900));
metric.add(ClusterFlowEvent.PASS, 2); metric.add(ClusterFlowEvent.PASS, 1);
metric.add(ClusterFlowEvent.PASS, 1); metric.add(ClusterFlowEvent.PASS, 2);
Assert.assertEquals(0, metric.tryOccupyNext(ClusterFlowEvent.PASS, 333, 900)); 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; 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.Assert;
import org.junit.Test; import org.junit.Test;
import org.mockito.MockedStatic;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -26,26 +28,28 @@ public class ClusterParamMetricTest extends AbstractTimeBasedTest {
@Test @Test
public void testClusterParamMetric() { public void testClusterParamMetric() {
setCurrentMillis(System.currentTimeMillis()); try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
Map<Object, Double> topMap = new HashMap<Object, Double>(); setCurrentMillis(mocked, System.currentTimeMillis());
ClusterParamMetric metric = new ClusterParamMetric(5, 25, 100); Map<Object, Double> topMap = new HashMap<Object, Double>();
metric.addValue("e1", -1); ClusterParamMetric metric = new ClusterParamMetric(5, 25, 100);
metric.addValue("e1", -2); metric.addValue("e1", -1);
metric.addValue("e2", 100); metric.addValue("e1", -2);
metric.addValue("e2", 23); metric.addValue("e2", 100);
metric.addValue("e3", 100); metric.addValue("e2", 23);
metric.addValue("e3", 230); metric.addValue("e3", 100);
Assert.assertEquals(-3, metric.getSum("e1")); metric.addValue("e3", 230);
Assert.assertEquals(-120, metric.getAvg("e1"), 0.01); Assert.assertEquals(-3, metric.getSum("e1"));
topMap.put("e3", (double) 13200); Assert.assertEquals(-120, metric.getAvg("e1"), 0.01);
Assert.assertEquals(topMap, metric.getTopValues(1)); topMap.put("e3", (double) 13200);
topMap.put("e2", (double) 4920); Assert.assertEquals(topMap, metric.getTopValues(1));
topMap.put("e1", (double) -120); topMap.put("e2", (double) 4920);
Assert.assertEquals(topMap, metric.getTopValues(5)); topMap.put("e1", (double) -120);
metric.addValue("e2", 100); Assert.assertEquals(topMap, metric.getTopValues(5));
metric.addValue("e2", 23); metric.addValue("e2", 100);
Assert.assertEquals(246, metric.getSum("e2")); metric.addValue("e2", 23);
Assert.assertEquals(9840, metric.getAvg("e2"), 0.01); Assert.assertEquals(246, metric.getSum("e2"));
Assert.assertEquals(9840, metric.getAvg("e2"), 0.01);
}
} }
@Test(expected = IllegalArgumentException.class) @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>
<dependency> <dependency>
<groupId>org.mockito</groupId> <groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId> <artifactId>mockito-inline</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
@ -43,16 +43,6 @@
<artifactId>java-hamcrest</artifactId> <artifactId>java-hamcrest</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </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> </dependencies>
<build> <build>
<plugins> <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.slotchain.StringResourceWrapper;
import com.alibaba.csp.sentinel.test.AbstractTimeBasedTest; import com.alibaba.csp.sentinel.test.AbstractTimeBasedTest;
import com.alibaba.csp.sentinel.util.TimeUtil;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; 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 * @author Carpenter Lee
@ -35,64 +38,68 @@ public class MetricExitCallbackTest extends AbstractTimeBasedTest {
@Test @Test
public void onExit() { public void onExit() {
FakeMetricExtension extension = new FakeMetricExtension(); try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
MetricExtensionProvider.addMetricExtension(extension); FakeMetricExtension extension = new FakeMetricExtension();
MetricExtensionProvider.addMetricExtension(extension);
MetricExitCallback exitCallback = new MetricExitCallback(); MetricExitCallback exitCallback = new MetricExitCallback();
StringResourceWrapper resourceWrapper = new StringResourceWrapper("resource", EntryType.OUT); StringResourceWrapper resourceWrapper = new StringResourceWrapper("resource", EntryType.OUT);
int count = 2; int count = 2;
Object[] args = {"args1", "args2"}; Object[] args = {"args1", "args2"};
long prevRt = 20; long prevRt = 20;
extension.rt = prevRt; extension.rt = prevRt;
extension.success = 6; extension.success = 6;
extension.thread = 10; extension.thread = 10;
Context context = mock(Context.class); Context context = mock(Context.class);
Entry entry = mock(Entry.class); Entry entry = mock(Entry.class);
// Mock current time // Mock current time
long curMillis = System.currentTimeMillis(); long curMillis = System.currentTimeMillis();
setCurrentMillis(curMillis); setCurrentMillis(mocked, curMillis);
int deltaMs = 100; int deltaMs = 100;
when(entry.getError()).thenReturn(null); when(entry.getError()).thenReturn(null);
when(entry.getCreateTimestamp()).thenReturn(curMillis - deltaMs); when(entry.getCreateTimestamp()).thenReturn(curMillis - deltaMs);
when(context.getCurEntry()).thenReturn(entry); when(context.getCurEntry()).thenReturn(entry);
exitCallback.onExit(context, resourceWrapper, count, args); exitCallback.onExit(context, resourceWrapper, count, args);
Assert.assertEquals(prevRt + deltaMs, extension.rt); Assert.assertEquals(prevRt + deltaMs, extension.rt);
Assert.assertEquals(extension.success, 6 + count); Assert.assertEquals(extension.success, 6 + count);
Assert.assertEquals(extension.thread, 10 - 1); Assert.assertEquals(extension.thread, 10 - 1);
}
} }
/** /**
* @author bill_yip * @author bill_yip
*/ */
@Test @Test
public void advancedExtensionOnExit() { public void advancedExtensionOnExit() {
FakeAdvancedMetricExtension extension = new FakeAdvancedMetricExtension(); try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
MetricExtensionProvider.addMetricExtension(extension); FakeAdvancedMetricExtension extension = new FakeAdvancedMetricExtension();
MetricExtensionProvider.addMetricExtension(extension);
MetricExitCallback exitCallback = new MetricExitCallback(); MetricExitCallback exitCallback = new MetricExitCallback();
StringResourceWrapper resourceWrapper = new StringResourceWrapper("resource", EntryType.OUT); StringResourceWrapper resourceWrapper = new StringResourceWrapper("resource", EntryType.OUT);
int count = 2; int count = 2;
Object[] args = {"args1", "args2"}; Object[] args = {"args1", "args2"};
long prevRt = 20; long prevRt = 20;
extension.rt = prevRt; extension.rt = prevRt;
extension.complete = 6; extension.complete = 6;
extension.concurrency = 10; extension.concurrency = 10;
Context context = mock(Context.class); Context context = mock(Context.class);
Entry entry = mock(Entry.class); Entry entry = mock(Entry.class);
// Mock current time // Mock current time
long curMillis = System.currentTimeMillis(); long curMillis = System.currentTimeMillis();
setCurrentMillis(curMillis); setCurrentMillis(mocked, curMillis);
int deltaMs = 100; int deltaMs = 100;
when(entry.getError()).thenReturn(null); when(entry.getError()).thenReturn(null);
when(entry.getCreateTimestamp()).thenReturn(curMillis - deltaMs); when(entry.getCreateTimestamp()).thenReturn(curMillis - deltaMs);
when(context.getCurEntry()).thenReturn(entry); when(context.getCurEntry()).thenReturn(entry);
exitCallback.onExit(context, resourceWrapper, count, args); exitCallback.onExit(context, resourceWrapper, count, args);
Assert.assertEquals(prevRt + deltaMs, extension.rt); Assert.assertEquals(prevRt + deltaMs, extension.rt);
Assert.assertEquals(extension.complete, 6 + count); Assert.assertEquals(extension.complete, 6 + count);
Assert.assertEquals(extension.concurrency, 10 - 1); 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.slots.block.degrade.circuitbreaker.EventObserverRegistry;
import com.alibaba.csp.sentinel.test.AbstractTimeBasedTest; import com.alibaba.csp.sentinel.test.AbstractTimeBasedTest;
import com.alibaba.csp.sentinel.util.TimeUtil;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.mockito.MockedStatic;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -55,187 +57,193 @@ public class CircuitBreakingIntegrationTest extends AbstractTimeBasedTest {
@Test @Test
public void testSlowRequestMode() { public void testSlowRequestMode() {
CircuitBreakerStateChangeObserver observer = mock(CircuitBreakerStateChangeObserver.class); try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
setCurrentMillis(System.currentTimeMillis() / 1000 * 1000); CircuitBreakerStateChangeObserver observer = mock(CircuitBreakerStateChangeObserver.class);
int retryTimeoutSec = 5; setCurrentMillis(mocked, System.currentTimeMillis() / 1000 * 1000);
int maxRt = 50; int retryTimeoutSec = 5;
int statIntervalMs = 20000; int maxRt = 50;
int minRequestAmount = 10; int statIntervalMs = 20000;
String res = "CircuitBreakingIntegrationTest_testSlowRequestMode"; int minRequestAmount = 10;
EventObserverRegistry.getInstance().addStateChangeObserver(res, observer); String res = "CircuitBreakingIntegrationTest_testSlowRequestMode";
DegradeRuleManager.loadRules(Arrays.asList( EventObserverRegistry.getInstance().addStateChangeObserver(res, observer);
new DegradeRule(res).setTimeWindow(retryTimeoutSec).setCount(maxRt) DegradeRuleManager.loadRules(Arrays.asList(
.setStatIntervalMs(statIntervalMs).setMinRequestAmount(minRequestAmount) new DegradeRule(res).setTimeWindow(retryTimeoutSec).setCount(maxRt)
.setSlowRatioThreshold(0.8d).setGrade(0) .setStatIntervalMs(statIntervalMs).setMinRequestAmount(minRequestAmount)
)); .setSlowRatioThreshold(0.8d).setGrade(0)
));
// Try first N requests where N = minRequestAmount. // Try first N requests where N = minRequestAmount.
for (int i = 0; i < minRequestAmount; i++) { for (int i = 0; i < minRequestAmount; i++) {
if (i < 7) { if (i < 7) {
assertTrue(entryAndSleepFor(res, maxRt + ThreadLocalRandom.current().nextInt(10, 20))); assertTrue(entryAndSleepFor(mocked, res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
} else { } else {
assertTrue(entryAndSleepFor(res, maxRt + ThreadLocalRandom.current().nextInt(-20, -10))); 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 @Test
public void testSlowRequestModeUseDefaultRule() { public void testSlowRequestModeUseDefaultRule() {
CircuitBreakerStateChangeObserver observer = mock(CircuitBreakerStateChangeObserver.class); try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
setCurrentMillis(System.currentTimeMillis() / 1000 * 1000); CircuitBreakerStateChangeObserver observer = mock(CircuitBreakerStateChangeObserver.class);
int retryTimeoutSec = 5; setCurrentMillis(mocked, System.currentTimeMillis() / 1000 * 1000);
int maxRt = 50; int retryTimeoutSec = 5;
int statIntervalMs = 20000; int maxRt = 50;
int minRequestAmount = 10; int statIntervalMs = 20000;
String res = "CircuitBreakingIntegrationTest_testSlowRequestModeUseDefaultRule"; int minRequestAmount = 10;
EventObserverRegistry.getInstance().addStateChangeObserver(res, observer); String res = "CircuitBreakingIntegrationTest_testSlowRequestModeUseDefaultRule";
EventObserverRegistry.getInstance().addStateChangeObserver(res, observer);
DefaultCircuitBreakerRuleManager.loadRules(Arrays.asList( DefaultCircuitBreakerRuleManager.loadRules(Arrays.asList(
new DegradeRule(DefaultCircuitBreakerRuleManager.DEFAULT_KEY).setTimeWindow(retryTimeoutSec).setCount(maxRt) new DegradeRule(DefaultCircuitBreakerRuleManager.DEFAULT_KEY).setTimeWindow(retryTimeoutSec).setCount(maxRt)
.setStatIntervalMs(statIntervalMs).setMinRequestAmount(minRequestAmount) .setStatIntervalMs(statIntervalMs).setMinRequestAmount(minRequestAmount)
.setSlowRatioThreshold(0.8d).setGrade(0))); .setSlowRatioThreshold(0.8d).setGrade(0)));
// Try first N requests where N = minRequestAmount. // Try first N requests where N = minRequestAmount.
for (int i = 0; i < minRequestAmount; i++) { for (int i = 0; i < minRequestAmount; i++) {
if (i < 7) { if (i < 7) {
assertTrue(entryAndSleepFor(res, maxRt + ThreadLocalRandom.current().nextInt(10, 20))); assertTrue(entryAndSleepFor(mocked, res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
} else { } else {
assertTrue(entryAndSleepFor(res, maxRt + ThreadLocalRandom.current().nextInt(-20, -10))); 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 @Test
public void testExceptionRatioMode() { public void testExceptionRatioMode() {
CircuitBreakerStateChangeObserver observer = mock(CircuitBreakerStateChangeObserver.class); try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
setCurrentMillis(System.currentTimeMillis() / 1000 * 1000); CircuitBreakerStateChangeObserver observer = mock(CircuitBreakerStateChangeObserver.class);
int retryTimeoutSec = 5; setCurrentMillis(mocked, System.currentTimeMillis() / 1000 * 1000);
double maxRatio = 0.5; int retryTimeoutSec = 5;
int statIntervalMs = 25000; double maxRatio = 0.5;
final int minRequestAmount = 10; int statIntervalMs = 25000;
String res = "CircuitBreakingIntegrationTest_testExceptionRatioMode"; final int minRequestAmount = 10;
EventObserverRegistry.getInstance().addStateChangeObserver(res, observer); String res = "CircuitBreakingIntegrationTest_testExceptionRatioMode";
DegradeRuleManager.loadRules(Arrays.asList( EventObserverRegistry.getInstance().addStateChangeObserver(res, observer);
new DegradeRule(res).setTimeWindow(retryTimeoutSec).setCount(maxRatio) DegradeRuleManager.loadRules(Arrays.asList(
.setStatIntervalMs(statIntervalMs).setMinRequestAmount(minRequestAmount) new DegradeRule(res).setTimeWindow(retryTimeoutSec).setCount(maxRatio)
.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO) .setStatIntervalMs(statIntervalMs).setMinRequestAmount(minRequestAmount)
)); .setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO)
));
// Try first N requests where N = minRequestAmount. // Try first N requests where N = minRequestAmount.
for (int i = 0; i < minRequestAmount - 1; i++) { for (int i = 0; i < minRequestAmount - 1; i++) {
if (i < 6) { if (i < 6) {
assertTrue(entryWithErrorIfPresent(res, new IllegalArgumentException())); assertTrue(entryWithErrorIfPresent(mocked, res, new IllegalArgumentException()));
} else { } else {
assertTrue(entryWithErrorIfPresent(res, null)); 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 @Test
public void testExceptionCountMode() { public void testExceptionCountMode() {
// TODO // TODO
} }
private void verifyState(List<CircuitBreaker> breakers, int target) { private void verifyState(List<CircuitBreaker> breakers, int target) {
int state = 0; int state = 0;
for (CircuitBreaker breaker : breakers) { for (CircuitBreaker breaker : breakers) {
@ -249,48 +257,50 @@ public class CircuitBreakingIntegrationTest extends AbstractTimeBasedTest {
} }
assertEquals(target, state); assertEquals(target, state);
} }
@Test @Test
public void testMultipleHalfOpenedBreakers() { public void testMultipleHalfOpenedBreakers() {
CircuitBreakerStateChangeObserver observer = mock(CircuitBreakerStateChangeObserver.class); try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
setCurrentMillis(System.currentTimeMillis() / 1000 * 1000); CircuitBreakerStateChangeObserver observer = mock(CircuitBreakerStateChangeObserver.class);
int retryTimeoutSec = 2; setCurrentMillis(mocked, System.currentTimeMillis() / 1000 * 1000);
int maxRt = 50; int retryTimeoutSec = 2;
int statIntervalMs = 20000; int maxRt = 50;
int minRequestAmount = 1; int statIntervalMs = 20000;
String res = "CircuitBreakingIntegrationTest_testMultipleHalfOpenedBreakers"; int minRequestAmount = 1;
EventObserverRegistry.getInstance().addStateChangeObserver(res, observer); String res = "CircuitBreakingIntegrationTest_testMultipleHalfOpenedBreakers";
// initial two rules EventObserverRegistry.getInstance().addStateChangeObserver(res, observer);
DegradeRuleManager.loadRules(Arrays.asList( // initial two rules
new DegradeRule(res).setTimeWindow(retryTimeoutSec).setCount(maxRt) DegradeRuleManager.loadRules(Arrays.asList(
.setStatIntervalMs(statIntervalMs).setMinRequestAmount(minRequestAmount) new DegradeRule(res).setTimeWindow(retryTimeoutSec).setCount(maxRt)
.setSlowRatioThreshold(0.8d).setGrade(0), .setStatIntervalMs(statIntervalMs).setMinRequestAmount(minRequestAmount)
new DegradeRule(res).setTimeWindow(retryTimeoutSec * 2).setCount(maxRt) .setSlowRatioThreshold(0.8d).setGrade(0),
.setStatIntervalMs(statIntervalMs).setMinRequestAmount(minRequestAmount) new DegradeRule(res).setTimeWindow(retryTimeoutSec * 2).setCount(maxRt)
.setSlowRatioThreshold(0.8d).setGrade(0) .setStatIntervalMs(statIntervalMs).setMinRequestAmount(minRequestAmount)
)); .setSlowRatioThreshold(0.8d).setGrade(0)
assertTrue(entryAndSleepFor(res, 100)); ));
// they are open now assertTrue(entryAndSleepFor(mocked, res, 100));
for (CircuitBreaker breaker : DegradeRuleManager.getCircuitBreakers(res)) { // they are open now
assertEquals(CircuitBreaker.State.OPEN, breaker.currentState()); 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.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import com.alibaba.csp.sentinel.util.TimeUtil;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -30,12 +31,13 @@ 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.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.test.AbstractTimeBasedTest; import com.alibaba.csp.sentinel.test.AbstractTimeBasedTest;
import org.mockito.MockedStatic;
/** /**
* @author Eric Zhao * @author Eric Zhao
*/ */
public class ExceptionCircuitBreakerTest extends AbstractTimeBasedTest { public class ExceptionCircuitBreakerTest extends AbstractTimeBasedTest {
@Before @Before
public void setUp() { public void setUp() {
DegradeRuleManager.loadRules(new ArrayList<DegradeRule>()); DegradeRuleManager.loadRules(new ArrayList<DegradeRule>());
@ -48,38 +50,40 @@ public class ExceptionCircuitBreakerTest extends AbstractTimeBasedTest {
@Test @Test
public void testRecordErrorOrSuccess() throws BlockException { public void testRecordErrorOrSuccess() throws BlockException {
String resource = "testRecordErrorOrSuccess"; try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
int retryTimeoutMillis = 10 * 1000; String resource = "testRecordErrorOrSuccess";
int retryTimeout = retryTimeoutMillis / 1000; int retryTimeoutMillis = 10 * 1000;
DegradeRule rule = new DegradeRule("abc") int retryTimeout = retryTimeoutMillis / 1000;
.setCount(0.2d) DegradeRule rule = new DegradeRule("abc")
.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO) .setCount(0.2d)
.setStatIntervalMs(20 * 1000) .setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO)
.setTimeWindow(retryTimeout) .setStatIntervalMs(20 * 1000)
.setMinRequestAmount(1); .setTimeWindow(retryTimeout)
rule.setResource(resource); .setMinRequestAmount(1);
DegradeRuleManager.loadRules(Arrays.asList(rule)); rule.setResource(resource);
DegradeRuleManager.loadRules(Arrays.asList(rule));
assertTrue(entryAndSleepFor(resource, 10)); assertTrue(entryAndSleepFor(mocked, resource, 10));
assertTrue(entryWithErrorIfPresent(resource, new IllegalArgumentException())); // -> open assertTrue(entryWithErrorIfPresent(mocked, resource, new IllegalArgumentException())); // -> open
assertFalse(entryWithErrorIfPresent(resource, new IllegalArgumentException())); assertFalse(entryWithErrorIfPresent(mocked, resource, new IllegalArgumentException()));
assertFalse(entryAndSleepFor(resource, 100)); assertFalse(entryAndSleepFor(mocked, resource, 100));
sleep(retryTimeoutMillis / 2); sleep(mocked, retryTimeoutMillis / 2);
assertFalse(entryAndSleepFor(resource, 100)); assertFalse(entryAndSleepFor(mocked, resource, 100));
sleep(retryTimeoutMillis / 2); sleep(mocked, retryTimeoutMillis / 2);
assertTrue(entryWithErrorIfPresent(resource, new IllegalArgumentException())); // -> half -> open assertTrue(entryWithErrorIfPresent(mocked, resource, new IllegalArgumentException())); // -> half -> open
assertFalse(entryAndSleepFor(resource, 100)); assertFalse(entryAndSleepFor(mocked, resource, 100));
assertFalse(entryAndSleepFor(resource, 100)); assertFalse(entryAndSleepFor(mocked, resource, 100));
sleep(retryTimeoutMillis); sleep(mocked, retryTimeoutMillis);
assertTrue(entryAndSleepFor(resource, 100)); // -> half -> closed assertTrue(entryAndSleepFor(mocked, resource, 100)); // -> half -> closed
assertTrue(entryAndSleepFor(resource, 100)); assertTrue(entryAndSleepFor(mocked, resource, 100));
assertTrue(entryAndSleepFor(resource, 100)); assertTrue(entryAndSleepFor(mocked, resource, 100));
assertTrue(entryAndSleepFor(resource, 100)); assertTrue(entryAndSleepFor(mocked, resource, 100));
assertTrue(entryAndSleepFor(resource, 100)); assertTrue(entryAndSleepFor(mocked, resource, 100));
assertTrue(entryAndSleepFor(resource, 100)); assertTrue(entryAndSleepFor(mocked, resource, 100));
assertTrue(entryAndSleepFor(resource, 100)); assertTrue(entryAndSleepFor(mocked, resource, 100));
assertTrue(entryWithErrorIfPresent(resource, new IllegalArgumentException())); assertTrue(entryWithErrorIfPresent(mocked, resource, new IllegalArgumentException()));
assertTrue(entryAndSleepFor(resource, 100)); 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.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.test.AbstractTimeBasedTest; import com.alibaba.csp.sentinel.test.AbstractTimeBasedTest;
import com.alibaba.csp.sentinel.util.TimeUtil;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.mockito.MockedStatic;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -31,28 +33,30 @@ public class ResponseTimeCircuitBreakerTest extends AbstractTimeBasedTest {
@Test @Test
public void testMaxSlowRatioThreshold() { public void testMaxSlowRatioThreshold() {
String resource = "testMaxSlowRatioThreshold"; try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
DegradeRule rule = new DegradeRule("resource") String resource = "testMaxSlowRatioThreshold";
.setCount(10) DegradeRule rule = new DegradeRule("resource")
.setGrade(RuleConstant.DEGRADE_GRADE_RT) .setCount(10)
.setMinRequestAmount(3) .setGrade(RuleConstant.DEGRADE_GRADE_RT)
.setSlowRatioThreshold(1) .setMinRequestAmount(3)
.setStatIntervalMs(5000) .setSlowRatioThreshold(1)
.setTimeWindow(5); .setStatIntervalMs(5000)
rule.setResource(resource); .setTimeWindow(5);
DegradeRuleManager.loadRules(Collections.singletonList(rule)); rule.setResource(resource);
DegradeRuleManager.loadRules(Collections.singletonList(rule));
assertTrue(entryAndSleepFor(resource, 20)); assertTrue(entryAndSleepFor(mocked, resource, 20));
assertTrue(entryAndSleepFor(resource, 20)); assertTrue(entryAndSleepFor(mocked, resource, 20));
assertTrue(entryAndSleepFor(resource, 20)); assertTrue(entryAndSleepFor(mocked, resource, 20));
// should be blocked, cause 3/3 requests' rt is bigger than max rt. // should be blocked, cause 3/3 requests' rt is bigger than max rt.
assertFalse(entryAndSleepFor(resource,20)); assertFalse(entryAndSleepFor(mocked, resource, 20));
sleep(1000); sleep(mocked, 1000);
assertFalse(entryAndSleepFor(resource,20)); assertFalse(entryAndSleepFor(mocked, resource, 20));
sleep(4000); 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.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import com.alibaba.csp.sentinel.util.TimeUtil;
import org.junit.Test; import org.junit.Test;
import com.alibaba.csp.sentinel.node.Node; import com.alibaba.csp.sentinel.node.Node;
import com.alibaba.csp.sentinel.test.AbstractTimeBasedTest; import com.alibaba.csp.sentinel.test.AbstractTimeBasedTest;
import org.mockito.MockedStatic;
/** /**
* @author jialiang.linjl * @author jialiang.linjl
@ -32,32 +34,34 @@ public class WarmUpControllerTest extends AbstractTimeBasedTest {
@Test @Test
public void testWarmUp() throws InterruptedException { 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());
Node node = mock(Node.class); setCurrentMillis(mocked, System.currentTimeMillis());
when(node.passQps()).thenReturn(8d); Node node = mock(Node.class);
when(node.previousPassQps()).thenReturn(1d);
assertFalse(warmupController.canPass(node, 1)); when(node.passQps()).thenReturn(8d);
when(node.previousPassQps()).thenReturn(1d);
when(node.passQps()).thenReturn(1d); assertFalse(warmupController.canPass(node, 1));
when(node.previousPassQps()).thenReturn(1d);
assertTrue(warmupController.canPass(node, 1)); when(node.passQps()).thenReturn(1d);
when(node.previousPassQps()).thenReturn(1d);
when(node.previousPassQps()).thenReturn(10d); assertTrue(warmupController.canPass(node, 1));
for (int i = 0; i < 100; i++) { when(node.previousPassQps()).thenReturn(10d);
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.concurrent.NamedThreadFactory;
import com.alibaba.csp.sentinel.test.AbstractTimeBasedTest; import com.alibaba.csp.sentinel.test.AbstractTimeBasedTest;
import com.alibaba.csp.sentinel.util.TimeUtil;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import org.mockito.MockedStatic;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
@ -52,74 +54,78 @@ public class TokenBucketTest extends AbstractTimeBasedTest {
@Test @Test
public void testForDefaultTokenBucket() throws InterruptedException { public void testForDefaultTokenBucket() throws InterruptedException {
long unitProduceNum = 1; try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
long maxTokenNum = 2; long unitProduceNum = 1;
long intervalInMs = 1000; long maxTokenNum = 2;
long testStart = System.currentTimeMillis(); long intervalInMs = 1000;
setCurrentMillis(testStart); 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)); assertTrue(defaultTokenBucket.tryConsume(1));
assertFalse(defaultTokenBucket.tryConsume(1)); assertFalse(defaultTokenBucket.tryConsume(1));
DefaultTokenBucket defaultTokenBucketFullStart = new DefaultTokenBucket(unitProduceNum, maxTokenNum, DefaultTokenBucket defaultTokenBucketFullStart = new DefaultTokenBucket(unitProduceNum, maxTokenNum,
true, intervalInMs); true, intervalInMs);
assertTrue(defaultTokenBucketFullStart.tryConsume(2)); assertTrue(defaultTokenBucketFullStart.tryConsume(2));
assertFalse(defaultTokenBucketFullStart.tryConsume(1)); assertFalse(defaultTokenBucketFullStart.tryConsume(1));
sleep(1000); sleep(mocked, 1000);
assertTrue(defaultTokenBucket.tryConsume(1)); assertTrue(defaultTokenBucket.tryConsume(1));
assertFalse(defaultTokenBucket.tryConsume(1)); assertFalse(defaultTokenBucket.tryConsume(1));
sleep(1000); sleep(mocked, 1000);
assertTrue(defaultTokenBucketFullStart.tryConsume(2)); assertTrue(defaultTokenBucketFullStart.tryConsume(2));
assertFalse(defaultTokenBucketFullStart.tryConsume(1)); assertFalse(defaultTokenBucketFullStart.tryConsume(1));
}
} }
@Test @Test
public void testForStrictTokenBucket() throws InterruptedException { public void testForStrictTokenBucket() throws InterruptedException {
long unitProduceNum = 5; try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
long maxTokenNum = 10; long unitProduceNum = 5;
long intervalInMs = 1000; long maxTokenNum = 10;
final int n = 64; long intervalInMs = 1000;
long testStart = System.currentTimeMillis(); final int n = 64;
setCurrentMillis(testStart); long testStart = System.currentTimeMillis();
setCurrentMillis(mocked, testStart);
final AtomicLong passNum = new AtomicLong(); final AtomicLong passNum = new AtomicLong();
final AtomicLong passNumFullStart = new AtomicLong(); final AtomicLong passNumFullStart = new AtomicLong();
final CountDownLatch countDownLatch = new CountDownLatch(n); final CountDownLatch countDownLatch = new CountDownLatch(n);
final CountDownLatch countDownLatchFullStart = new CountDownLatch(n); final CountDownLatch countDownLatchFullStart = new CountDownLatch(n);
final StrictTokenBucket strictTokenBucket = new StrictTokenBucket(unitProduceNum, maxTokenNum, intervalInMs); final StrictTokenBucket strictTokenBucket = new StrictTokenBucket(unitProduceNum, maxTokenNum, intervalInMs);
final StrictTokenBucket strictTokenBucketFullStart = new StrictTokenBucket(unitProduceNum, maxTokenNum, true, final StrictTokenBucket strictTokenBucketFullStart = new StrictTokenBucket(unitProduceNum, maxTokenNum, true,
intervalInMs); intervalInMs);
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
threadPoolExecutor.execute(new Runnable() { threadPoolExecutor.execute(new Runnable() {
@Override @Override
public void run() { public void run() {
if (strictTokenBucket.tryConsume(1)) { if (strictTokenBucket.tryConsume(1)) {
passNum.incrementAndGet(); passNum.incrementAndGet();
}
countDownLatch.countDown();
} }
countDownLatch.countDown(); });
} threadPoolExecutor.execute(new Runnable() {
}); @Override
threadPoolExecutor.execute(new Runnable() { public void run() {
@Override if (strictTokenBucketFullStart.tryConsume(1)) {
public void run() { passNumFullStart.incrementAndGet();
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 java.util.concurrent.atomic.AtomicInteger;
import com.alibaba.csp.sentinel.util.TimeUtil;
import org.junit.Test; import org.junit.Test;
import com.alibaba.csp.sentinel.test.AbstractTimeBasedTest; import com.alibaba.csp.sentinel.test.AbstractTimeBasedTest;
import org.mockito.MockedStatic;
import static org.junit.Assert.*; import static org.junit.Assert.*;
@ -30,36 +32,38 @@ public class LeapArrayTest extends AbstractTimeBasedTest {
@Test @Test
public void testGetValidHead() { public void testGetValidHead() {
int windowLengthInMs = 100; try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
int intervalInMs = 1000; int windowLengthInMs = 100;
int sampleCount = intervalInMs / windowLengthInMs; int intervalInMs = 1000;
LeapArray<AtomicInteger> leapArray = new LeapArray<AtomicInteger>(sampleCount, intervalInMs) { int sampleCount = intervalInMs / windowLengthInMs;
@Override LeapArray<AtomicInteger> leapArray = new LeapArray<AtomicInteger>(sampleCount, intervalInMs) {
public AtomicInteger newEmptyBucket(long time) { @Override
return new AtomicInteger(0); 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 assertSame(expected1, leapArray.getValidHead());
protected WindowWrap<AtomicInteger> resetWindowTo(WindowWrap<AtomicInteger> windowWrap, long startTime) { sleep(mocked, windowLengthInMs);
windowWrap.resetTo(startTime); assertSame(expected2, leapArray.getValidHead());
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(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 com.alibaba.csp.sentinel.util.TimeUtil;
import org.junit.Test; import org.junit.Test;
import org.mockito.MockedStatic;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
@ -27,113 +28,120 @@ public class OccupiableBucketLeapArrayTest extends AbstractTimeBasedTest {
@Test @Test
public void testNewWindow() { public void testNewWindow() {
long currentTime = System.currentTimeMillis(); try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
setCurrentMillis(currentTime); long currentTime = System.currentTimeMillis();
OccupiableBucketLeapArray leapArray = new OccupiableBucketLeapArray(sampleCount, intervalInMs); setCurrentMillis(mocked, currentTime);
OccupiableBucketLeapArray leapArray = new OccupiableBucketLeapArray(sampleCount, intervalInMs);
WindowWrap<MetricBucket> currentWindow = leapArray.currentWindow(currentTime); WindowWrap<MetricBucket> currentWindow = leapArray.currentWindow(currentTime);
currentWindow.value().addPass(1); currentWindow.value().addPass(1);
assertEquals(currentWindow.value().pass(), 1L); assertEquals(currentWindow.value().pass(), 1L);
leapArray.addWaiting(currentTime + windowLengthInMs, 1);
assertEquals(leapArray.currentWaiting(), 1);
assertEquals(currentWindow.value().pass(), 1L);
leapArray.addWaiting(currentTime + windowLengthInMs, 1);
assertEquals(leapArray.currentWaiting(), 1);
assertEquals(currentWindow.value().pass(), 1L);
}
} }
@Test @Test
public void testWindowInOneInterval() { public void testWindowInOneInterval() {
OccupiableBucketLeapArray leapArray = new OccupiableBucketLeapArray(sampleCount, intervalInMs); try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
long currentTime = System.currentTimeMillis(); OccupiableBucketLeapArray leapArray = new OccupiableBucketLeapArray(sampleCount, intervalInMs);
setCurrentMillis(currentTime); long currentTime = System.currentTimeMillis();
setCurrentMillis(mocked, currentTime);
WindowWrap<MetricBucket> currentWindow = leapArray.currentWindow(currentTime); WindowWrap<MetricBucket> currentWindow = leapArray.currentWindow(currentTime);
currentWindow.value().addPass(1); currentWindow.value().addPass(1);
assertEquals(currentWindow.value().pass(), 1L); assertEquals(currentWindow.value().pass(), 1L);
leapArray.addWaiting(currentTime + windowLengthInMs, 2); leapArray.addWaiting(currentTime + windowLengthInMs, 2);
assertEquals(leapArray.currentWaiting(), 2); assertEquals(leapArray.currentWaiting(), 2);
assertEquals(currentWindow.value().pass(), 1L); assertEquals(currentWindow.value().pass(), 1L);
leapArray.currentWindow(currentTime + windowLengthInMs); leapArray.currentWindow(currentTime + windowLengthInMs);
List<MetricBucket> values = leapArray.values(currentTime + windowLengthInMs); List<MetricBucket> values = leapArray.values(currentTime + windowLengthInMs);
assertEquals(values.size(), 2); assertEquals(values.size(), 2);
long sum = 0; long sum = 0;
for (MetricBucket bucket : values) { for (MetricBucket bucket : values) {
sum += bucket.pass(); sum += bucket.pass();
}
assertEquals(sum, 3);
} }
assertEquals(sum, 3);
} }
@Test @Test
public void testMultiThreadUpdateEmptyWindow() throws Exception { public void testMultiThreadUpdateEmptyWindow() throws Exception {
final long time = System.currentTimeMillis(); try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
setCurrentMillis(time); final long time = System.currentTimeMillis();
final int nThreads = 16; setCurrentMillis(mocked, time);
final OccupiableBucketLeapArray leapArray = new OccupiableBucketLeapArray(sampleCount, intervalInMs); final int nThreads = 16;
final CountDownLatch latch = new CountDownLatch(nThreads); final OccupiableBucketLeapArray leapArray = new OccupiableBucketLeapArray(sampleCount, intervalInMs);
Runnable task = new Runnable() { final CountDownLatch latch = new CountDownLatch(nThreads);
@Override Runnable task = new Runnable() {
public void run() { @Override
leapArray.currentWindow(time).value().addPass(1); public void run() {
leapArray.addWaiting(time + windowLengthInMs, 1); leapArray.currentWindow(time).value().addPass(1);
latch.countDown(); 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++) { latch.await();
new Thread(task).start();
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 @Test
public void testWindowAfterOneInterval() { public void testWindowAfterOneInterval() {
OccupiableBucketLeapArray leapArray = new OccupiableBucketLeapArray(sampleCount, intervalInMs); try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
long currentTime = System.currentTimeMillis(); OccupiableBucketLeapArray leapArray = new OccupiableBucketLeapArray(sampleCount, intervalInMs);
setCurrentMillis(currentTime); long currentTime = System.currentTimeMillis();
setCurrentMillis(mocked, currentTime);
System.out.println(currentTime); System.out.println(currentTime);
for (int i = 0; i < intervalInSec * 1000 / windowLengthInMs; i++) { for (int i = 0; i < intervalInSec * 1000 / windowLengthInMs; i++) {
WindowWrap<MetricBucket> currentWindow = leapArray.currentWindow(currentTime + i * windowLengthInMs); WindowWrap<MetricBucket> currentWindow = leapArray.currentWindow(currentTime + i * windowLengthInMs);
currentWindow.value().addPass(1); currentWindow.value().addPass(1);
leapArray.addWaiting(currentTime + (i + 1) * windowLengthInMs, 1); leapArray.addWaiting(currentTime + (i + 1) * windowLengthInMs, 1);
System.out.println(currentTime + i * windowLengthInMs); System.out.println(currentTime + i * windowLengthInMs);
leapArray.debug(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; 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.Entry;
import com.alibaba.csp.sentinel.SphU; import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.Tracer; import com.alibaba.csp.sentinel.Tracer;
import com.alibaba.csp.sentinel.slots.block.BlockException; 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 com.alibaba.csp.sentinel.util.TimeUtil;
import java.util.concurrent.ThreadLocalRandom;
/** /**
* Mock support for {@link TimeUtil}. * Mock support for {@link TimeUtil}.
* *
* @author jason * @author jason
*/ */
@RunWith(PowerMockRunner.class) @RunWith(MockitoJUnitRunner.class)
@PrepareForTest({ TimeUtil.class })
public abstract class AbstractTimeBasedTest { public abstract class AbstractTimeBasedTest {
private long currentMillis = 0; private long currentMillis = 0;
{ public MockedStatic<TimeUtil> mockTimeUtil() {
PowerMockito.mockStatic(TimeUtil.class); MockedStatic<TimeUtil> mocked = Mockito.mockStatic(TimeUtil.class);
PowerMockito.when(TimeUtil.currentTimeMillis()).thenReturn(currentMillis); mocked.when(TimeUtil::currentTimeMillis).thenReturn(currentMillis);
return mocked;
} }
protected final void useActualTime() { protected final void useActualTime(MockedStatic<TimeUtil> mocked) {
PowerMockito.when(TimeUtil.currentTimeMillis()).thenCallRealMethod(); mocked.when(TimeUtil::currentTimeMillis).thenCallRealMethod();
} }
protected final void setCurrentMillis(long cur) { protected final void setCurrentMillis(MockedStatic<TimeUtil> mocked, long cur) {
currentMillis = 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; currentMillis += t;
PowerMockito.when(TimeUtil.currentTimeMillis()).thenReturn(currentMillis); mocked.when(TimeUtil::currentTimeMillis).thenReturn(currentMillis);
} }
protected final void sleepSecond(int timeSec) { protected final void sleepSecond(MockedStatic<TimeUtil> mocked, long timeSec) {
sleep(timeSec * 1000); 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; Entry entry = null;
try { try {
entry = SphU.entry(res); entry = SphU.entry(res);
sleep(sleepMs); sleep(mocked, sleepMs);
} catch (BlockException ex) { } catch (BlockException ex) {
return false; return false;
} catch (Exception ex) { } catch (Exception ex) {
@ -79,14 +79,14 @@ public abstract class AbstractTimeBasedTest {
return true; return true;
} }
protected final boolean entryWithErrorIfPresent(String res, Exception ex) { protected final boolean entryWithErrorIfPresent(MockedStatic<TimeUtil> mocked, String res, Exception ex) {
Entry entry = null; Entry entry = null;
try { try {
entry = SphU.entry(res); entry = SphU.entry(res);
if (ex != null) { if (ex != null) {
Tracer.traceEntry(ex, entry); Tracer.traceEntry(ex, entry);
} }
sleep(ThreadLocalRandom.current().nextInt(5, 10)); sleep(mocked, ThreadLocalRandom.current().nextInt(5, 10));
} catch (BlockException b) { } catch (BlockException b) {
return false; return false;
} finally { } finally {

View File

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

View File

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

View File

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

View File

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