Support jdk17 (#3339)
Adjust the test logic, use jdk17 to build, 8, 11, 17 to run
This commit is contained in:
parent
2b7a989e29
commit
8fef1b5eee
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
74
pom.xml
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue