Browse Source

Update test cases for circuit breaking

Signed-off-by: Eric Zhao <sczyh16@gmail.com>
master
Eric Zhao 4 years ago
parent
commit
07b811196b
5 changed files with 416 additions and 184 deletions
  1. +213
    -0
      sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/block/degrade/CircuitBreakingIntegrationTest.java
  2. +41
    -2
      sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/block/degrade/DegradeRuleManagerTest.java
  3. +51
    -0
      sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/block/degrade/DegradeRuleTest.java
  4. +0
    -182
      sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/block/degrade/DegradeTest.java
  5. +111
    -0
      sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/block/degrade/circuitbreaker/ExceptionCircuitBreakerTest.java

+ 213
- 0
sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/block/degrade/CircuitBreakingIntegrationTest.java View File

@@ -0,0 +1,213 @@
/*
* 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.slots.block.degrade;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.Tracer;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.degrade.circuitbreaker.CircuitBreaker.State;
import com.alibaba.csp.sentinel.slots.block.degrade.circuitbreaker.CircuitBreakerStateChangeObserver;
import com.alibaba.csp.sentinel.slots.block.degrade.circuitbreaker.EventObserverRegistry;
import com.alibaba.csp.sentinel.test.AbstractTimeBasedTest;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.ThreadLocalRandom;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.*;

/**
* @author jialiang.linjl
* @author Eric Zhao
*/
public class CircuitBreakingIntegrationTest extends AbstractTimeBasedTest {

@Before
public void setUp() {
DegradeRuleManager.loadRules(new ArrayList<DegradeRule>());
}

@After
public void tearDown() throws Exception {
DegradeRuleManager.loadRules(new ArrayList<DegradeRule>());
}

private boolean entryAndSleepFor(String res, int sleepMs) {
Entry entry = null;
try {
entry = SphU.entry(res);
sleep(sleepMs);
} catch (BlockException ex) {
return false;
} catch (Exception ex) {
Tracer.traceEntry(ex, entry);
} finally {
if (entry != null) {
entry.exit();
}
}
return true;
}

private boolean entryWithErrorIfPresent(String res, Exception ex) {
Entry entry = null;
try {
entry = SphU.entry(res);
if (ex != null) {
Tracer.traceEntry(ex, entry);
}
sleep(ThreadLocalRandom.current().nextInt(5, 10));
} catch (BlockException b) {
return false;
} finally {
if (entry != null) {
entry.exit();
}
}
return true;
}

@Test
public void testSlowRequestMode() throws Exception {
CircuitBreakerStateChangeObserver observer = mock(CircuitBreakerStateChangeObserver.class);
setCurrentMillis(System.currentTimeMillis() / 1000 * 1000);
int retryTimeoutSec = 5;
int maxRt = 50;
int statIntervalMs = 20000;
int minRequestAmount = 10;
String res = "CircuitBreakingIntegrationTest_testSlowRequestMode";
EventObserverRegistry.getInstance().addStateChangeObserver(res, observer);
DegradeRuleManager.loadRules(Arrays.asList(
new DegradeRule(res).setTimeWindow(retryTimeoutSec).setCount(maxRt)
.setStatIntervalMs(statIntervalMs).setMinRequestAmount(minRequestAmount)
.setSlowRatioThreshold(0.8d).setGrade(0)
));

// Try first N requests where N = minRequestAmount.
for (int i = 0; i < minRequestAmount; i++) {
if (i < 7) {
assertTrue(entryAndSleepFor(res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
} else {
assertTrue(entryAndSleepFor(res, maxRt + ThreadLocalRandom.current().nextInt(-20, -10)));
}
}

// Till now slow ratio should be 70%.
assertTrue(entryAndSleepFor(res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
assertTrue(entryAndSleepFor(res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
assertTrue(entryAndSleepFor(res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
assertTrue(entryAndSleepFor(res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
assertTrue(entryAndSleepFor(res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
assertTrue(entryAndSleepFor(res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));
// Circuit breaker has transformed to OPEN since here.
verify(observer)
.onStateChange(eq(State.CLOSED), eq(State.OPEN), any(DegradeRule.class), anyDouble());
assertEquals(State.OPEN, DegradeRuleManager.getCircuitBreakers(res).get(0).currentState());
assertFalse(entryAndSleepFor(res, 1));

sleepSecond(1);
assertFalse(entryAndSleepFor(res, 1));
sleepSecond(retryTimeoutSec);
// Test HALF-OPEN to OPEN.
assertTrue(entryAndSleepFor(res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));

verify(observer)
.onStateChange(eq(State.OPEN), eq(State.HALF_OPEN), any(DegradeRule.class), nullable(Double.class));
verify(observer)
.onStateChange(eq(State.HALF_OPEN), eq(State.OPEN), any(DegradeRule.class), anyDouble());
// Wait for next retry timeout;
reset(observer);
sleepSecond(retryTimeoutSec + 1);
assertTrue(entryAndSleepFor(res, maxRt - ThreadLocalRandom.current().nextInt(10, 20)));
verify(observer)
.onStateChange(eq(State.OPEN), eq(State.HALF_OPEN), any(DegradeRule.class), nullable(Double.class));
verify(observer)
.onStateChange(eq(State.HALF_OPEN), eq(State.CLOSED), any(DegradeRule.class), nullable(Double.class));
// Now circuit breaker has been closed.
assertTrue(entryAndSleepFor(res, maxRt + ThreadLocalRandom.current().nextInt(10, 20)));

EventObserverRegistry.getInstance().removeStateChangeObserver(res);
}

@Test
public void testExceptionRatioMode() throws Exception {
CircuitBreakerStateChangeObserver observer = mock(CircuitBreakerStateChangeObserver.class);
setCurrentMillis(System.currentTimeMillis() / 1000 * 1000);
int retryTimeoutSec = 5;
double maxRatio = 0.5;
int statIntervalMs = 25000;
final int minRequestAmount = 10;
String res = "CircuitBreakingIntegrationTest_testExceptionRatioMode";
EventObserverRegistry.getInstance().addStateChangeObserver(res, observer);
DegradeRuleManager.loadRules(Arrays.asList(
new DegradeRule(res).setTimeWindow(retryTimeoutSec).setCount(maxRatio)
.setStatIntervalMs(statIntervalMs).setMinRequestAmount(minRequestAmount)
.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO)
));

// Try first N requests where N = minRequestAmount.
for (int i = 0; i < minRequestAmount - 1; i++) {
if (i < 6) {
assertTrue(entryWithErrorIfPresent(res, new IllegalArgumentException()));
} else {
assertTrue(entryWithErrorIfPresent(res, null));
}
}

// 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
public void testExceptionCountMode() throws Throwable {
// TODO
}

}

+ 41
- 2
sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/block/degrade/DegradeRuleManagerTest.java View File

@@ -15,8 +15,14 @@
*/
package com.alibaba.csp.sentinel.slots.block.degrade;

import java.util.ArrayList;
import java.util.Arrays;

import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.degrade.circuitbreaker.CircuitBreaker;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.*;
@@ -28,6 +34,32 @@ import static org.junit.Assert.*;
*/
public class DegradeRuleManagerTest {

@Before
public void setUp() throws Exception {
DegradeRuleManager.loadRules(new ArrayList<DegradeRule>());
}

@After
public void tearDown() throws Exception {
DegradeRuleManager.loadRules(new ArrayList<DegradeRule>());
}

@Test
public void loadSameRuleUseSameCircuitBreaker() {
String resource = "loadSameRuleUseSameCircuitBreaker";
DegradeRule rule = new DegradeRule(resource)
.setCount(100)
.setSlowRatioThreshold(0.9d)
.setTimeWindow(20)
.setStatIntervalMs(20000);
DegradeRuleManager.loadRules(Arrays.asList(rule));
CircuitBreaker cb = DegradeRuleManager.getCircuitBreakers(resource).get(0);

DegradeRuleManager.loadRules(Arrays.asList(rule,
new DegradeRule("abc").setTimeWindow(20).setCount(20).setSlowRatioThreshold(0.8d)));
assertSame(cb, DegradeRuleManager.getCircuitBreakers(resource).get(0));
}

@Test
public void testIsValidRule() {
DegradeRule rule1 = new DegradeRule("abc");
@@ -46,13 +78,19 @@ public class DegradeRuleManagerTest {
DegradeRule rule5 = new DegradeRule("Sentinel")
.setCount(97)
.setGrade(RuleConstant.DEGRADE_GRADE_RT)
.setTimeWindow(15)
.setRtSlowRequestAmount(0);
.setSlowRatioThreshold(15)
.setTimeWindow(15);
DegradeRule rule6 = new DegradeRule("Sentinel")
.setCount(0.93d)
.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO)
.setTimeWindow(20)
.setMinRequestAmount(0);
DegradeRule rule7 = new DegradeRule("Sentinel")
.setCount(100)
.setSlowRatioThreshold(0.8d)
.setTimeWindow(10)
.setStatIntervalMs(0)
.setMinRequestAmount(20);
assertFalse(DegradeRuleManager.isValidRule(rule1));
assertFalse(DegradeRuleManager.isValidRule(rule2));
assertFalse(DegradeRuleManager.isValidRule(rule3));
@@ -61,5 +99,6 @@ public class DegradeRuleManagerTest {
assertFalse(DegradeRuleManager.isValidRule(rule4));
assertFalse(DegradeRuleManager.isValidRule(rule5));
assertFalse(DegradeRuleManager.isValidRule(rule6));
assertFalse(DegradeRuleManager.isValidRule(rule7));
}
}

+ 51
- 0
sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/block/degrade/DegradeRuleTest.java View File

@@ -0,0 +1,51 @@
/*
* 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.slots.block.degrade;

import com.alibaba.csp.sentinel.slots.block.RuleConstant;

import org.junit.Test;

import static org.junit.Assert.*;

/**
* @author Eric Zhao
*/
public class DegradeRuleTest {

@Test
public void testRuleEquals() {
DegradeRule degradeRule1 = new DegradeRule();
DegradeRule degradeRule2 = new DegradeRule();

int minRequestAmount = 20;
double count = 1.0;
int timeWindow = 2;
degradeRule1.setMinRequestAmount(minRequestAmount);
degradeRule1.setCount(count);
degradeRule1.setTimeWindow(timeWindow);
degradeRule1.setGrade(RuleConstant.DEGRADE_GRADE_RT);

degradeRule2.setMinRequestAmount(minRequestAmount);
degradeRule2.setCount(count);
degradeRule2.setGrade(RuleConstant.DEGRADE_GRADE_RT);
degradeRule2.setTimeWindow(timeWindow);
assertEquals(degradeRule1, degradeRule2);

degradeRule2.setMinRequestAmount(100);
assertNotEquals(degradeRule1, degradeRule2);
}
}

+ 0
- 182
sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/block/degrade/DegradeTest.java View File

@@ -1,182 +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.slots.block.degrade;

import com.alibaba.csp.sentinel.EntryType;
import com.alibaba.csp.sentinel.context.Context;
import com.alibaba.csp.sentinel.node.ClusterNode;
import com.alibaba.csp.sentinel.node.DefaultNode;
import com.alibaba.csp.sentinel.slotchain.StringResourceWrapper;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot;
import org.junit.Test;

import java.util.concurrent.TimeUnit;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

/**
* @author jialiang.linjl
*/
public class DegradeTest {

@Test
public void testAverageRtDegrade() throws InterruptedException {
String key = "test_degrade_average_rt";
ClusterNode cn = mock(ClusterNode.class);
ClusterBuilderSlot.getClusterNodeMap().put(new StringResourceWrapper(key, EntryType.IN), cn);

Context context = mock(Context.class);
DefaultNode node = mock(DefaultNode.class);
when(node.getClusterNode()).thenReturn(cn);
when(cn.avgRt()).thenReturn(2d);

int rtSlowRequestAmount = 10;
DegradeRule rule = new DegradeRule();
rule.setCount(1);
rule.setResource(key);
rule.setTimeWindow(2);
rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
rule.setRtSlowRequestAmount(rtSlowRequestAmount);

//Will true
for (int i = 0; i < rtSlowRequestAmount - 1; i++) {
assertTrue(rule.passCheck(context, node, 1));
}

// The third time will fail.
assertFalse(rule.passCheck(context, node, 1));
assertFalse(rule.passCheck(context, node, 1));

// Restore.
TimeUnit.MILLISECONDS.sleep(2200);
assertTrue(rule.passCheck(context, node, 1));
}

@Test
public void testExceptionRatioModeDegrade() throws Throwable {
String key = "test_degrade_exception_ratio";
ClusterNode cn = mock(ClusterNode.class);
ClusterBuilderSlot.getClusterNodeMap().put(new StringResourceWrapper(key, EntryType.IN), cn);

Context context = mock(Context.class);
DefaultNode node = mock(DefaultNode.class);
when(node.getClusterNode()).thenReturn(cn);

DegradeRule rule = new DegradeRule();
rule.setCount(0.15);
rule.setResource(key);
rule.setTimeWindow(2);
rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO);
rule.setMinRequestAmount(20);


// Will true. While totalQps < minRequestAmount
when(cn.totalQps()).thenReturn(8d);
assertTrue(rule.passCheck(context, node, 1));

// Will true.
when(cn.totalQps()).thenReturn(21d);
when(cn.successQps()).thenReturn(9d);
when(cn.exceptionQps()).thenReturn(9d);
assertTrue(rule.passCheck(context, node, 1));


// Will true. While totalQps > minRequestAmount and exceptionRation < count
when(cn.totalQps()).thenReturn(100d);
when(cn.successQps()).thenReturn(90d);
when(cn.exceptionQps()).thenReturn(10d);
assertTrue(rule.passCheck(context, node, 1));

// Will fail. While totalQps > minRequestAmount and exceptionRation > count
rule.setMinRequestAmount(5);
when(cn.totalQps()).thenReturn(12d);
when(cn.successQps()).thenReturn(8d);
when(cn.exceptionQps()).thenReturn(6d);
assertFalse(rule.passCheck(context, node, 1));

// Restore from the degrade timeout.
TimeUnit.MILLISECONDS.sleep(2200);

// Will pass.
when(cn.totalQps()).thenReturn(106d);
when(cn.successQps()).thenReturn(100d);
assertTrue(rule.passCheck(context, node, 1));
}

@Test
public void testExceptionCountModeDegrade() throws Throwable {
String key = "test_degrade_exception_count";
ClusterNode cn = mock(ClusterNode.class);
when(cn.totalException()).thenReturn(10L);
ClusterBuilderSlot.getClusterNodeMap().put(new StringResourceWrapper(key, EntryType.IN), cn);

Context context = mock(Context.class);
DefaultNode node = mock(DefaultNode.class);
when(node.getClusterNode()).thenReturn(cn);

DegradeRule rule = new DegradeRule();
rule.setCount(4);
rule.setResource(key);
rule.setTimeWindow(2);
rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);

when(cn.totalException()).thenReturn(4L);

// Will fail.
assertFalse(rule.passCheck(context, node, 1));

// Restore from the degrade timeout.
TimeUnit.MILLISECONDS.sleep(2200);

when(cn.totalException()).thenReturn(0L);
// Will pass.
assertTrue(rule.passCheck(context, node, 1));
}

@Test
public void testEquals() {
DegradeRule degradeRule1 = new DegradeRule();
DegradeRule degradeRule2 = new DegradeRule();
assertTrue(degradeRule1.equals(degradeRule2));

int rtSlowRequestAmount = 10;
int minRequestAmount = 20;
double count = 1.0;
int timeWindow = 2;
degradeRule1.setRtSlowRequestAmount(rtSlowRequestAmount);
degradeRule1.setMinRequestAmount(minRequestAmount);
degradeRule1.setCount(count);
degradeRule1.setTimeWindow(timeWindow);
degradeRule1.setGrade(RuleConstant.DEGRADE_GRADE_RT);

degradeRule2.setRtSlowRequestAmount(rtSlowRequestAmount);
degradeRule2.setMinRequestAmount(minRequestAmount);
degradeRule2.setCount(count);
degradeRule2.setGrade(RuleConstant.DEGRADE_GRADE_RT);
degradeRule2.setTimeWindow(timeWindow);
assertTrue(degradeRule1.equals(degradeRule2));

degradeRule2.setMinRequestAmount(100);
assertFalse(degradeRule1.equals(degradeRule2));


}

}

+ 111
- 0
sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/block/degrade/circuitbreaker/ExceptionCircuitBreakerTest.java View File

@@ -0,0 +1,111 @@
/*
* Copyright 1999-2019 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.slots.block.degrade.circuitbreaker;

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.circuitbreaker.CircuitBreaker.State;
import com.alibaba.csp.sentinel.slots.block.degrade.circuitbreaker.ExceptionCircuitBreaker.SimpleErrorCounter;
import com.alibaba.csp.sentinel.slots.statistic.base.LeapArray;
import com.alibaba.csp.sentinel.slots.statistic.base.WindowWrap;
import com.alibaba.csp.sentinel.test.AbstractTimeBasedTest;

import org.junit.Test;

import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

/**
* @author Eric Zhao
*/
public class ExceptionCircuitBreakerTest extends AbstractTimeBasedTest {

@Test
@SuppressWarnings("unchecked")
public void testStateChangeAndTryAcquire() {
int retryTimeout = 10;
DegradeRule rule = new DegradeRule("abc")
.setCount(0.5d)
.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO)
.setStatIntervalMs(20 * 1000)
.setTimeWindow(retryTimeout)
.setMinRequestAmount(10);
LeapArray<SimpleErrorCounter> stat = mock(LeapArray.class);
SimpleErrorCounter counter = new SimpleErrorCounter();
WindowWrap<SimpleErrorCounter> bucket = new WindowWrap<>(20000, 0, counter);
when(stat.currentWindow()).thenReturn(bucket);

ExceptionCircuitBreaker cb = new ExceptionCircuitBreaker(rule, stat);

assertTrue(cb.tryPass());
assertTrue(cb.tryPass());

setCurrentMillis(System.currentTimeMillis());
cb.fromCloseToOpen(0.52d);
assertEquals(State.OPEN, cb.currentState());

assertFalse(cb.tryPass());
assertFalse(cb.tryPass());

// Wait for next retry checkpoint.
sleepSecond(retryTimeout);
sleep(100);
// Try a request to trigger state transformation.
assertTrue(cb.tryPass());
assertEquals(State.HALF_OPEN, cb.currentState());

// Mark this request as error
cb.onRequestComplete(20, new IllegalArgumentException());
assertEquals(State.OPEN, cb.currentState());

// Wait for next retry checkpoint.
sleepSecond(retryTimeout);
sleep(100);
assertTrue(cb.tryPass());
assertEquals(State.HALF_OPEN, cb.currentState());

setCurrentMillis(System.currentTimeMillis());
// Mark this request as success.
cb.onRequestComplete(20, null);
assertEquals(State.CLOSED, cb.currentState());
}

@Test
@SuppressWarnings("unchecked")
public void testRecordErrorOrSuccess() {
DegradeRule rule = new DegradeRule("abc")
.setCount(0.5d)
.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO)
.setStatIntervalMs(20 * 1000)
.setTimeWindow(10)
.setMinRequestAmount(10);
LeapArray<SimpleErrorCounter> stat = mock(LeapArray.class);
SimpleErrorCounter counter = new SimpleErrorCounter();
WindowWrap<SimpleErrorCounter> bucket = new WindowWrap<>(20000, 0, counter);
when(stat.currentWindow()).thenReturn(bucket);

CircuitBreaker cb = new ExceptionCircuitBreaker(rule, stat);
cb.onRequestComplete(15, null);

assertEquals(1L, counter.getTotalCount().longValue());
assertEquals(0L, counter.getErrorCount().longValue());

cb.onRequestComplete(15, new IllegalArgumentException());
assertEquals(2L, counter.getTotalCount().longValue());
assertEquals(1L, counter.getErrorCount().longValue());
}
}

Loading…
Cancel
Save