Skip to content

Commit

Permalink
Update test cases for Context and CtSph
Browse files Browse the repository at this point in the history
Signed-off-by: Eric Zhao <[email protected]>
  • Loading branch information
sczyh30 committed Sep 24, 2018
1 parent 391cb4e commit 00d2856
Show file tree
Hide file tree
Showing 3 changed files with 272 additions and 7 deletions.
228 changes: 228 additions & 0 deletions sentinel-core/src/test/java/com/alibaba/csp/sentinel/CtSphTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
package com.alibaba.csp.sentinel;

import com.alibaba.csp.sentinel.context.Context;
import com.alibaba.csp.sentinel.context.ContextTestUtil;
import com.alibaba.csp.sentinel.context.ContextUtil;
import com.alibaba.csp.sentinel.node.DefaultNode;
import com.alibaba.csp.sentinel.slotchain.AbstractLinkedProcessorSlot;
import com.alibaba.csp.sentinel.slotchain.DefaultProcessorSlotChain;
import com.alibaba.csp.sentinel.slotchain.ProcessorSlot;
import com.alibaba.csp.sentinel.slotchain.ProcessorSlotChain;
import com.alibaba.csp.sentinel.slotchain.ResourceWrapper;
import com.alibaba.csp.sentinel.slotchain.StringResourceWrapper;
import com.alibaba.csp.sentinel.slots.block.BlockException;

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

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

/**
* Test cases for Sentinel internal {@link CtSph}.
*
* @author Eric Zhao
*/
public class CtSphTest {

private final CtSph ctSph = new CtSph();

@Test
public void testCustomContextEntryWithFullContextSize() {
String resourceName = "testCustomContextSyncEntryWithFullContextSize";
fillFullContext();
ResourceWrapper resourceWrapper = new StringResourceWrapper(resourceName, EntryType.IN);
String contextName = "custom-context-" + System.currentTimeMillis();
ContextUtil.enter(contextName, "9527");

// Prepare a slot that "should not pass". If entered the slot, exception will be thrown.
addShouldNotPassSlotFor(resourceWrapper);

Entry entry = null;
try {
entry = ctSph.entry(resourceWrapper, 1);
} catch (BlockException ex) {
fail("Unexpected blocked: " + ex.getClass().getCanonicalName());
} finally {
if (entry != null) {
entry.exit();
}
ContextUtil.exit();
}
}

@Test
public void testDefaultContextEntryWithFullContextSize() {
String resourceName = "testDefaultContextSyncEntryWithFullContextSize";
fillFullContext();
ResourceWrapper resourceWrapper = new StringResourceWrapper(resourceName, EntryType.IN);

// Prepare a slot that "should pass".
ShouldPassSlot slot = addShouldPassSlotFor(resourceWrapper);
assertFalse(slot.entered || slot.exited);

Entry entry = null;
try {
entry = ctSph.entry(resourceWrapper, 1);
assertTrue(ContextUtil.isDefaultContext(ContextUtil.getContext()));
assertTrue(slot.entered);
} catch (BlockException ex) {
fail("Unexpected blocked: " + ex.getClass().getCanonicalName());
} finally {
if (entry != null) {
entry.exit();
assertTrue(slot.exited);
}
}
}

@Test
public void testEntryEntryWhenSwitchOff() {
// Turn off the switch.
Constants.ON = false;

String resourceNameA = "resSync";
ResourceWrapper resourceWrapperA = new StringResourceWrapper(resourceNameA, EntryType.IN);

// Prepare a slot that "should not pass". If entered the slot, exception will be thrown.
addShouldNotPassSlotFor(resourceWrapperA);

Entry entry = null;
try {
entry = ctSph.entry(resourceWrapperA, 1);
} catch (BlockException ex) {
fail("Unexpected blocked: " + ex.getClass().getCanonicalName());
} finally {
if (entry != null) {
entry.exit();
}
Constants.ON = true;
}
}

@Test
public void testEntryAmountExceededForSyncEntry() {
fillFullResources();
Entry entry = null;
try {
entry = ctSph.entry("testSync", EntryType.IN, 1);
assertSame(entry, ContextUtil.getContext().getCurEntry());
} catch (BlockException ex) {
fail("Unexpected blocked: " + ex.getClass().getCanonicalName());
} finally {
if (entry != null) {
entry.exit();
}
}
}

@Test
public void testLookUpSlotChain() {
ResourceWrapper r1 = new StringResourceWrapper("firstRes", EntryType.IN);
assertFalse(CtSph.getChainMap().containsKey(r1));
ProcessorSlot<Object> chainR1 = ctSph.lookProcessChain(r1);
assertNotNull("The slot chain for r1 should be created", chainR1);
assertSame("Should return the cached slot chain once it has been created", chainR1, ctSph.lookProcessChain(r1));

fillFullResources();
ResourceWrapper r2 = new StringResourceWrapper("secondRes", EntryType.IN);
assertFalse(CtSph.getChainMap().containsKey(r2));
assertNull("The slot chain for r2 should not be created because amount exceeded", ctSph.lookProcessChain(r2));
assertNull(ctSph.lookProcessChain(r2));
}

private void fillFullContext() {
for (int i = 0; i < Constants.MAX_CONTEXT_NAME_SIZE; i++) {
ContextUtil.enter("test-context-" + i);
ContextUtil.exit();
}
}

private void fillFullResources() {
for (int i = 0; i < Constants.MAX_SLOT_CHAIN_SIZE; i++) {
ResourceWrapper resourceWrapper = new StringResourceWrapper("test-resource-" + i, EntryType.IN);
CtSph.getChainMap().put(resourceWrapper, new DefaultProcessorSlotChain());
}
}

private void addShouldNotPassSlotFor(ResourceWrapper resourceWrapper) {
ProcessorSlotChain slotChain = new DefaultProcessorSlotChain();
slotChain.addLast(new ShouldNotPassSlot());
CtSph.getChainMap().put(resourceWrapper, slotChain);
}

private ShouldPassSlot addShouldPassSlotFor(ResourceWrapper resourceWrapper) {
ProcessorSlotChain slotChain = new DefaultProcessorSlotChain();
ShouldPassSlot shouldPassSlot = new ShouldPassSlot();
slotChain.addLast(shouldPassSlot);
CtSph.getChainMap().put(resourceWrapper, slotChain);
return shouldPassSlot;
}

private MustBlockSlot addMustBlockSlot(ResourceWrapper resourceWrapper) {
ProcessorSlotChain slotChain = new DefaultProcessorSlotChain();
MustBlockSlot mustBlockSlot = new MustBlockSlot();
slotChain.addLast(mustBlockSlot);
CtSph.getChainMap().put(resourceWrapper, slotChain);
return mustBlockSlot;
}

private class ShouldNotPassSlot extends AbstractLinkedProcessorSlot<DefaultNode> {
@Override
public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode param, int count,
Object... args) {
throw new IllegalStateException("Should not enter this slot!");
}

@Override
public void exit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) {
throw new IllegalStateException("Should not exit this slot!");
}
}

private class MustBlockSlot extends AbstractLinkedProcessorSlot<DefaultNode> {
boolean exited = false;

@Override
public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode param, int count,
Object... args) throws Throwable {
throw new BlockException("custom") {};
}

@Override
public void exit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) {
exited = true;
}
}

private class ShouldPassSlot extends AbstractLinkedProcessorSlot<DefaultNode> {
boolean entered = false;
boolean exited = false;

@Override
public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode param, int count,
Object... args) {
entered = true;
}

@Override
public void exit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) {
exited = true;
}
}

@Before
public void setUp() throws Exception {
ContextTestUtil.cleanUpContext();
ContextTestUtil.resetContextMap();
CtSph.resetChainMap();
}

@After
public void tearDown() throws Exception {
ContextTestUtil.cleanUpContext();
ContextTestUtil.resetContextMap();
CtSph.resetChainMap();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,7 @@ public void setUp() {

@After
public void cleanUp() {
Context context = ContextUtil.getContext();
if (context != null) {
context.setCurEntry(null);
ContextUtil.exit();
}
ContextTestUtil.cleanUpContext();
}

@Test
Expand Down Expand Up @@ -81,7 +77,6 @@ private void fillContext() {
}

private void resetContextMap() {
ContextUtil.resetContextMap();
Constants.ROOT.removeChildList();
ContextTestUtil.resetContextMap();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* 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.context;

import com.alibaba.csp.sentinel.Constants;

/**
* Util class for testing context-related functions.
* Only for test. DO NOT USE IN PRODUCTION!
*
* @author Eric Zhao
*/
public final class ContextTestUtil {

public static void cleanUpContext() {
Context context = ContextUtil.getContext();
if (context != null) {
context.setCurEntry(null);
ContextUtil.exit();
}
}

public static void resetContextMap() {
ContextUtil.resetContextMap();
Constants.ROOT.removeChildList();
}

private ContextTestUtil() {}
}

0 comments on commit 00d2856

Please sign in to comment.