Signed-off-by: Eric Zhao <sczyh16@gmail.com>master
@@ -0,0 +1,178 @@ | |||
/* | |||
* 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.flow; | |||
import java.util.Arrays; | |||
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.After; | |||
import org.junit.Before; | |||
import org.junit.Test; | |||
import static org.junit.Assert.*; | |||
import static org.mockito.Mockito.*; | |||
/** | |||
* @author Eric Zhao | |||
*/ | |||
public class FlowRuleCheckerTest { | |||
@Test | |||
public void testDefaultLimitAppFlowSelectNode() { | |||
DefaultNode node = mock(DefaultNode.class); | |||
ClusterNode cn = mock(ClusterNode.class); | |||
when(node.getClusterNode()).thenReturn(cn); | |||
Context context = mock(Context.class); | |||
// limitApp: default | |||
FlowRule rule = new FlowRule("testDefaultLimitAppFlowSelectNode").setCount(1); | |||
assertEquals(cn, FlowRuleChecker.selectNodeByRequesterAndStrategy(rule, context, node)); | |||
} | |||
@Test | |||
public void testCustomOriginFlowSelectNode() { | |||
String origin = "appA"; | |||
String limitAppB = "appB"; | |||
DefaultNode node = mock(DefaultNode.class); | |||
DefaultNode originNode = mock(DefaultNode.class); | |||
ClusterNode cn = mock(ClusterNode.class); | |||
when(node.getClusterNode()).thenReturn(cn); | |||
Context context = mock(Context.class); | |||
when(context.getOrigin()).thenReturn(origin); | |||
when(context.getOriginNode()).thenReturn(originNode); | |||
FlowRule rule = new FlowRule("testCustomOriginFlowSelectNode").setCount(1); | |||
rule.setLimitApp(origin); | |||
// Origin matches, return the origin node. | |||
assertEquals(originNode, FlowRuleChecker.selectNodeByRequesterAndStrategy(rule, context, node)); | |||
rule.setLimitApp(limitAppB); | |||
// Origin mismatch, no node found. | |||
assertNull(FlowRuleChecker.selectNodeByRequesterAndStrategy(rule, context, node)); | |||
} | |||
@Test | |||
public void testOtherOriginFlowSelectNode() { | |||
String originA = "appA"; | |||
String originB = "appB"; | |||
DefaultNode node = mock(DefaultNode.class); | |||
DefaultNode originNode = mock(DefaultNode.class); | |||
ClusterNode cn = mock(ClusterNode.class); | |||
when(node.getClusterNode()).thenReturn(cn); | |||
Context context = mock(Context.class); | |||
when(context.getOriginNode()).thenReturn(originNode); | |||
FlowRule ruleA = new FlowRule("testOtherOriginFlowSelectNode").setCount(1); | |||
ruleA.setLimitApp(originA); | |||
FlowRule ruleB = new FlowRule("testOtherOriginFlowSelectNode").setCount(2); | |||
ruleB.setLimitApp(RuleConstant.LIMIT_APP_OTHER); | |||
FlowRuleManager.loadRules(Arrays.asList(ruleA, ruleB)); | |||
// Origin matches other, return the origin node. | |||
when(context.getOrigin()).thenReturn(originB); | |||
assertEquals(originNode, FlowRuleChecker.selectNodeByRequesterAndStrategy(ruleB, context, node)); | |||
// Origin matches limitApp of an existing rule, so no nodes are selected. | |||
when(context.getOrigin()).thenReturn(originA); | |||
assertNull(FlowRuleChecker.selectNodeByRequesterAndStrategy(ruleB, context, node)); | |||
} | |||
@Test | |||
public void testSelectNodeForEmptyReference() { | |||
DefaultNode node = mock(DefaultNode.class); | |||
Context context = mock(Context.class); | |||
FlowRule rule = new FlowRule("testSelectNodeForEmptyReference") | |||
.setCount(1) | |||
.setStrategy(RuleConstant.STRATEGY_CHAIN); | |||
assertNull(FlowRuleChecker.selectReferenceNode(rule, context, node)); | |||
} | |||
@Test | |||
public void testSelectNodeForRelateReference() { | |||
String refResource = "testSelectNodeForRelateReference_refResource"; | |||
DefaultNode node = mock(DefaultNode.class); | |||
ClusterNode refCn = mock(ClusterNode.class); | |||
ClusterBuilderSlot.getClusterNodeMap().put(new StringResourceWrapper(refResource, EntryType.IN), refCn); | |||
Context context = mock(Context.class); | |||
FlowRule rule = new FlowRule("testSelectNodeForRelateReference") | |||
.setCount(1) | |||
.setStrategy(RuleConstant.STRATEGY_RELATE) | |||
.setRefResource(refResource); | |||
assertEquals(refCn, FlowRuleChecker.selectReferenceNode(rule, context, node)); | |||
} | |||
@Test | |||
public void testSelectReferenceNodeForContextEntrance() { | |||
String contextName = "good_context"; | |||
DefaultNode node = mock(DefaultNode.class); | |||
Context context = mock(Context.class); | |||
FlowRule rule = new FlowRule("testSelectReferenceNodeForContextEntrance") | |||
.setCount(1) | |||
.setStrategy(RuleConstant.STRATEGY_CHAIN) | |||
.setRefResource(contextName); | |||
when(context.getName()).thenReturn(contextName); | |||
assertEquals(node, FlowRuleChecker.selectReferenceNode(rule, context, node)); | |||
when(context.getName()).thenReturn("other_context"); | |||
assertNull(FlowRuleChecker.selectReferenceNode(rule, context, node)); | |||
} | |||
@Test | |||
public void testPassCheckNullLimitApp() { | |||
FlowRule rule = new FlowRule("abc").setCount(1); | |||
rule.setLimitApp(null); | |||
assertTrue(FlowRuleChecker.passCheck(rule, null, null, 1)); | |||
} | |||
@Test | |||
public void testPassCheckSelectEmptyNodeSuccess() { | |||
FlowRule rule = new FlowRule("abc").setCount(1); | |||
rule.setLimitApp("abc"); | |||
DefaultNode node = mock(DefaultNode.class); | |||
Context context = mock(Context.class); | |||
when(context.getOrigin()).thenReturn("def"); | |||
assertTrue(FlowRuleChecker.passCheck(rule, context, node, 1)); | |||
} | |||
@Before | |||
public void setUp() throws Exception { | |||
FlowRuleManager.loadRules(null); | |||
ClusterBuilderSlot.getClusterNodeMap().clear(); | |||
} | |||
@After | |||
public void tearDown() throws Exception { | |||
FlowRuleManager.loadRules(null); | |||
ClusterBuilderSlot.getClusterNodeMap().clear(); | |||
} | |||
} |
@@ -19,6 +19,7 @@ import static org.junit.Assert.assertTrue; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
import org.junit.Ignore; | |||
import org.junit.Test; | |||
import com.alibaba.csp.sentinel.context.Context; | |||
@@ -30,6 +31,7 @@ import com.alibaba.csp.sentinel.slots.block.flow.controller.DefaultController; | |||
/** | |||
* @author jialiang.linjl | |||
*/ | |||
@Ignore("Deprecated test for legacy FlowRule") | |||
public class FlowRuleTest { | |||
@Test | |||
@@ -0,0 +1,92 @@ | |||
/* | |||
* 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.flow; | |||
import java.util.Collections; | |||
import com.alibaba.csp.sentinel.EntryType; | |||
import com.alibaba.csp.sentinel.context.Context; | |||
import com.alibaba.csp.sentinel.context.ContextTestUtil; | |||
import com.alibaba.csp.sentinel.node.DefaultNode; | |||
import com.alibaba.csp.sentinel.slotchain.ResourceWrapper; | |||
import com.alibaba.csp.sentinel.slotchain.StringResourceWrapper; | |||
import org.junit.After; | |||
import org.junit.Before; | |||
import org.junit.Test; | |||
import static org.junit.Assert.*; | |||
import static org.mockito.Mockito.*; | |||
/** | |||
* @author Eric Zhao | |||
*/ | |||
public class FlowSlotTest { | |||
@Before | |||
public void setUp() { | |||
ContextTestUtil.cleanUpContext(); | |||
FlowRuleManager.loadRules(null); | |||
} | |||
@After | |||
public void tearDown() { | |||
ContextTestUtil.cleanUpContext(); | |||
FlowRuleManager.loadRules(null); | |||
} | |||
@Test | |||
public void testCheckFlowPass() throws Exception { | |||
FlowSlot flowSlot = mock(FlowSlot.class); | |||
Context context = mock(Context.class); | |||
DefaultNode node = mock(DefaultNode.class); | |||
doCallRealMethod().when(flowSlot).checkFlow(any(ResourceWrapper.class), any(Context.class), | |||
any(DefaultNode.class), anyInt()); | |||
String resA = "resAK"; | |||
String resB = "resBK"; | |||
FlowRule rule1 = new FlowRule(resA).setCount(10); | |||
FlowRule rule2 = new FlowRule(resB).setCount(10); | |||
// Here we only load rules for resA. | |||
FlowRuleManager.loadRules(Collections.singletonList(rule1)); | |||
when(flowSlot.canPassCheck(eq(rule1), any(Context.class), any(DefaultNode.class), anyInt())) | |||
.thenReturn(true); | |||
when(flowSlot.canPassCheck(eq(rule2), any(Context.class), any(DefaultNode.class), anyInt())) | |||
.thenReturn(false); | |||
flowSlot.checkFlow(new StringResourceWrapper(resA, EntryType.IN), context, node, 1); | |||
flowSlot.checkFlow(new StringResourceWrapper(resB, EntryType.IN), context, node, 1); | |||
} | |||
@Test(expected = FlowException.class) | |||
public void testCheckFlowBlock() throws Exception { | |||
FlowSlot flowSlot = mock(FlowSlot.class); | |||
Context context = mock(Context.class); | |||
DefaultNode node = mock(DefaultNode.class); | |||
doCallRealMethod().when(flowSlot).checkFlow(any(ResourceWrapper.class), any(Context.class), | |||
any(DefaultNode.class), anyInt()); | |||
String resA = "resAK"; | |||
FlowRule rule = new FlowRule(resA).setCount(10); | |||
FlowRuleManager.loadRules(Collections.singletonList(rule)); | |||
when(flowSlot.canPassCheck(any(FlowRule.class), any(Context.class), any(DefaultNode.class), anyInt())) | |||
.thenReturn(false); | |||
flowSlot.checkFlow(new StringResourceWrapper(resA, EntryType.IN), context, node, 1); | |||
} | |||
} |
@@ -1,48 +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.flow; | |||
import java.util.Arrays; | |||
import org.junit.Test; | |||
import com.alibaba.csp.sentinel.context.ContextUtil; | |||
import com.alibaba.csp.sentinel.slots.block.RuleConstant; | |||
/** | |||
* @author jialiang.linjl | |||
*/ | |||
public class WarmUpFlowTest { | |||
@Test | |||
public void testWarmupFlowControl() { | |||
FlowRule flowRule = new FlowRule(); | |||
flowRule.setResource("testWarmupFlowControl"); | |||
flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS); | |||
flowRule.setCount(10); | |||
flowRule.setStrategy(RuleConstant.STRATEGY_DIRECT); | |||
flowRule.setWarmUpPeriodSec(10); | |||
flowRule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_WARM_UP); | |||
FlowRuleManager.loadRules(Arrays.asList(flowRule)); | |||
ContextUtil.enter("test"); | |||
ContextUtil.exit(); | |||
} | |||
} |
@@ -0,0 +1,44 @@ | |||
package com.alibaba.csp.sentinel.slots.block.flow.controller; | |||
import com.alibaba.csp.sentinel.node.Node; | |||
import com.alibaba.csp.sentinel.slots.block.RuleConstant; | |||
import com.alibaba.csp.sentinel.slots.block.flow.TrafficShapingController; | |||
import org.junit.Test; | |||
import static org.junit.Assert.*; | |||
import static org.mockito.Mockito.*; | |||
/** | |||
* @author Eric Zhao | |||
*/ | |||
public class DefaultControllerTest { | |||
@Test | |||
public void testCanPassForQps() { | |||
long threshold = 10; | |||
TrafficShapingController controller = new DefaultController(threshold, RuleConstant.FLOW_GRADE_QPS); | |||
Node node = mock(Node.class); | |||
when(node.passQps()).thenReturn(threshold - 1) | |||
.thenReturn(threshold); | |||
assertTrue(controller.canPass(node, 1)); | |||
assertFalse(controller.canPass(node, 1)); | |||
} | |||
@Test | |||
public void testCanPassForThreadCount() { | |||
int threshold = 8; | |||
TrafficShapingController controller = new DefaultController(threshold, RuleConstant.FLOW_GRADE_THREAD); | |||
Node node = mock(Node.class); | |||
when(node.curThreadNum()).thenReturn(threshold - 1) | |||
.thenReturn(threshold); | |||
assertTrue(controller.canPass(node, 1)); | |||
assertFalse(controller.canPass(node, 1)); | |||
} | |||
@Test | |||
public void testCanPassForQpsMultiThread() { | |||
} | |||
} |
@@ -13,7 +13,7 @@ | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package com.alibaba.csp.sentinel.slots.block.flow; | |||
package com.alibaba.csp.sentinel.slots.block.flow.controller; | |||
import static org.junit.Assert.assertTrue; | |||
import static org.mockito.Mockito.mock; |
@@ -13,7 +13,7 @@ | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package com.alibaba.csp.sentinel.slots.block.flow; | |||
package com.alibaba.csp.sentinel.slots.block.flow.controller; | |||
import static org.junit.Assert.assertFalse; | |||
import static org.junit.Assert.assertTrue; |
@@ -1,4 +1,4 @@ | |||
package com.alibaba.csp.sentinel.slots.block.flow; | |||
package com.alibaba.csp.sentinel.slots.block.flow.controller; | |||
import com.alibaba.csp.sentinel.node.Node; | |||
import com.alibaba.csp.sentinel.node.StatisticNode; |