From f60394c651846b15220c9a86c23d833d90da9e35 Mon Sep 17 00:00:00 2001 From: Eric Zhao Date: Thu, 21 Mar 2019 16:25:07 +0800 Subject: [PATCH] Add test cases for sentinel-annotation-aspectj (#581) Signed-off-by: Eric Zhao --- .../sentinel-annotation-aspectj/pom.xml | 38 +++++- .../AbstractSentinelAspectSupport.java | 2 +- .../aspectj/ResourceMetadataRegistry.java | 14 ++ .../AbstractSentinelAspectSupportTest.java | 39 ++++++ .../annotation/aspectj/MethodWrapperTest.java | 43 ++++++ .../aspectj/ResourceMetadataRegistryTest.java | 85 ++++++++++++ .../SentinelAnnotationIntegrationTest.java | 124 ++++++++++++++++++ .../integration/config/AopTestConfig.java | 36 +++++ .../integration/service/FooService.java | 59 +++++++++ .../aspectj/integration/service/FooUtil.java | 31 +++++ 10 files changed, 469 insertions(+), 2 deletions(-) create mode 100644 sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/AbstractSentinelAspectSupportTest.java create mode 100644 sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/MethodWrapperTest.java create mode 100644 sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/ResourceMetadataRegistryTest.java create mode 100644 sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/integration/SentinelAnnotationIntegrationTest.java create mode 100644 sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/integration/config/AopTestConfig.java create mode 100644 sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/integration/service/FooService.java create mode 100644 sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/integration/service/FooUtil.java diff --git a/sentinel-extension/sentinel-annotation-aspectj/pom.xml b/sentinel-extension/sentinel-annotation-aspectj/pom.xml index 94166837..e463d181 100644 --- a/sentinel-extension/sentinel-annotation-aspectj/pom.xml +++ b/sentinel-extension/sentinel-annotation-aspectj/pom.xml @@ -14,6 +14,8 @@ 1.9.2 + + 5.1.5.RELEASE @@ -32,6 +34,40 @@ aspectjweaver ${aspectj.version} + + + junit + junit + test + + + org.assertj + assertj-core + test + + + org.mockito + mockito-core + test + + + org.springframework + spring-context + ${spring.test.version} + test + + + org.springframework + spring-aop + ${spring.test.version} + test + + + org.springframework + spring-test + ${spring.test.version} + test + - \ No newline at end of file + diff --git a/sentinel-extension/sentinel-annotation-aspectj/src/main/java/com/alibaba/csp/sentinel/annotation/aspectj/AbstractSentinelAspectSupport.java b/sentinel-extension/sentinel-annotation-aspectj/src/main/java/com/alibaba/csp/sentinel/annotation/aspectj/AbstractSentinelAspectSupport.java index fe72e4f7..6a13765d 100644 --- a/sentinel-extension/sentinel-annotation-aspectj/src/main/java/com/alibaba/csp/sentinel/annotation/aspectj/AbstractSentinelAspectSupport.java +++ b/sentinel-extension/sentinel-annotation-aspectj/src/main/java/com/alibaba/csp/sentinel/annotation/aspectj/AbstractSentinelAspectSupport.java @@ -36,7 +36,7 @@ import java.util.Arrays; */ public abstract class AbstractSentinelAspectSupport { - protected String getResourceName(String resourceName, Method method) { + protected String getResourceName(String resourceName, /*@NonNull*/ Method method) { // If resource name is present in annotation, use this value. if (StringUtil.isNotBlank(resourceName)) { return resourceName; diff --git a/sentinel-extension/sentinel-annotation-aspectj/src/main/java/com/alibaba/csp/sentinel/annotation/aspectj/ResourceMetadataRegistry.java b/sentinel-extension/sentinel-annotation-aspectj/src/main/java/com/alibaba/csp/sentinel/annotation/aspectj/ResourceMetadataRegistry.java index fcb276f4..25bb1bfd 100644 --- a/sentinel-extension/sentinel-annotation-aspectj/src/main/java/com/alibaba/csp/sentinel/annotation/aspectj/ResourceMetadataRegistry.java +++ b/sentinel-extension/sentinel-annotation-aspectj/src/main/java/com/alibaba/csp/sentinel/annotation/aspectj/ResourceMetadataRegistry.java @@ -56,4 +56,18 @@ final class ResourceMetadataRegistry { private static String getKey(Class clazz, String name) { return String.format("%s:%s", clazz.getCanonicalName(), name); } + + /** + * Only for internal test. + */ + static void clearFallbackMap() { + FALLBACK_MAP.clear(); + } + + /** + * Only for internal test. + */ + static void clearBlockHandlerMap() { + BLOCK_HANDLER_MAP.clear(); + } } diff --git a/sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/AbstractSentinelAspectSupportTest.java b/sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/AbstractSentinelAspectSupportTest.java new file mode 100644 index 00000000..ec68306f --- /dev/null +++ b/sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/AbstractSentinelAspectSupportTest.java @@ -0,0 +1,39 @@ +/* + * 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.annotation.aspectj; + +import com.alibaba.csp.sentinel.annotation.aspectj.integration.service.FooService; +import org.junit.Test; + +import java.lang.reflect.Method; + +import static org.assertj.core.api.Assertions.*; + +/** + * @author Eric Zhao + */ +public class AbstractSentinelAspectSupportTest extends AbstractSentinelAspectSupport { + + @Test + public void testGetResourceName() throws Exception { + Method method = FooService.class.getMethod("random"); + String resourceName = "someRandom"; + String expectedResolvedName = FooService.class.getName() + ":random()"; + assertThat(getResourceName(resourceName, method)).isEqualTo(resourceName); + assertThat(getResourceName(null, method)).isEqualTo(expectedResolvedName); + assertThat(getResourceName("", method)).isEqualTo(expectedResolvedName); + } +} diff --git a/sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/MethodWrapperTest.java b/sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/MethodWrapperTest.java new file mode 100644 index 00000000..4961958b --- /dev/null +++ b/sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/MethodWrapperTest.java @@ -0,0 +1,43 @@ +/* + * 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.annotation.aspectj; + +import org.junit.Test; + +import java.lang.reflect.Method; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Eric Zhao + */ +public class MethodWrapperTest { + + @Test + public void testWrapMethod() { + Method method = String.class.getMethods()[0]; + MethodWrapper m = MethodWrapper.wrap(method); + assertThat(m.isPresent()).isTrue(); + assertThat(m.getMethod()).isSameAs(method); + } + + @Test + public void testNone() { + MethodWrapper none = MethodWrapper.none(); + assertThat(none.isPresent()).isFalse(); + assertThat(none.getMethod()).isNull(); + } +} diff --git a/sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/ResourceMetadataRegistryTest.java b/sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/ResourceMetadataRegistryTest.java new file mode 100644 index 00000000..eac25b91 --- /dev/null +++ b/sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/ResourceMetadataRegistryTest.java @@ -0,0 +1,85 @@ +/* + * 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.annotation.aspectj; + +import com.alibaba.csp.sentinel.annotation.aspectj.integration.service.FooService; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.lang.reflect.Method; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Eric Zhao + */ +public class ResourceMetadataRegistryTest { + + @Before + public void setUp() throws Exception { + ResourceMetadataRegistry.clearBlockHandlerMap(); + ResourceMetadataRegistry.clearFallbackMap(); + } + + @After + public void tearDown() throws Exception { + ResourceMetadataRegistry.clearBlockHandlerMap(); + ResourceMetadataRegistry.clearFallbackMap(); + } + + @Test + public void testUpdateThenLookupFallback() { + Class clazz = FooService.class; + String methodName = "someMethodFallback"; + Method method = clazz.getMethods()[0]; + assertThat(ResourceMetadataRegistry.lookupFallback(clazz, methodName)).isNull(); + + ResourceMetadataRegistry.updateFallbackFor(clazz, methodName, null); + assertThat(ResourceMetadataRegistry.lookupFallback(clazz, methodName).isPresent()).isFalse(); + + ResourceMetadataRegistry.updateFallbackFor(clazz, methodName, method); + MethodWrapper wrapper = ResourceMetadataRegistry.lookupFallback(clazz, methodName); + assertThat(wrapper.isPresent()).isTrue(); + assertThat(wrapper.getMethod()).isSameAs(method); + } + + @Test + public void testUpdateThenLookupBlockHandler() { + Class clazz = FooService.class; + String methodName = "someMethodBlockHand;er"; + Method method = clazz.getMethods()[1]; + assertThat(ResourceMetadataRegistry.lookupBlockHandler(clazz, methodName)).isNull(); + + ResourceMetadataRegistry.updateBlockHandlerFor(clazz, methodName, null); + assertThat(ResourceMetadataRegistry.lookupBlockHandler(clazz, methodName).isPresent()).isFalse(); + + ResourceMetadataRegistry.updateBlockHandlerFor(clazz, methodName, method); + MethodWrapper wrapper = ResourceMetadataRegistry.lookupBlockHandler(clazz, methodName); + assertThat(wrapper.isPresent()).isTrue(); + assertThat(wrapper.getMethod()).isSameAs(method); + } + + @Test(expected = IllegalArgumentException.class) + public void testUpdateBlockHandlerBadArgument() { + ResourceMetadataRegistry.updateBlockHandlerFor(null, "sxs", String.class.getMethods()[0]); + } + + @Test(expected = IllegalArgumentException.class) + public void testUpdateFallbackBadArgument() { + ResourceMetadataRegistry.updateBlockHandlerFor(String.class, "", String.class.getMethods()[0]); + } +} diff --git a/sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/integration/SentinelAnnotationIntegrationTest.java b/sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/integration/SentinelAnnotationIntegrationTest.java new file mode 100644 index 00000000..547994ff --- /dev/null +++ b/sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/integration/SentinelAnnotationIntegrationTest.java @@ -0,0 +1,124 @@ +/* + * 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.annotation.aspectj.integration; + +import com.alibaba.csp.sentinel.annotation.aspectj.integration.config.AopTestConfig; +import com.alibaba.csp.sentinel.annotation.aspectj.integration.service.FooService; +import com.alibaba.csp.sentinel.annotation.aspectj.integration.service.FooUtil; +import com.alibaba.csp.sentinel.node.ClusterNode; +import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; +import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; +import com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot; +import com.alibaba.csp.sentinel.util.MethodUtil; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.springframework.aop.support.AopUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests; + +import java.lang.reflect.UndeclaredThrowableException; +import java.util.ArrayList; +import java.util.Collections; + +import static org.assertj.core.api.Assertions.*; + +/** + * Integration test for Sentinel annotation AspectJ extension. + * + * @author Eric Zhao + */ +@ContextConfiguration(classes = {SentinelAnnotationIntegrationTest.class, AopTestConfig.class}) +public class SentinelAnnotationIntegrationTest extends AbstractJUnit4SpringContextTests { + + @Autowired + private FooService fooService; + + @Test + public void testProxySuccessful() { + assertThat(AopUtils.isAopProxy(fooService)).isTrue(); + assertThat(AopUtils.isCglibProxy(fooService)).isTrue(); + } + + @Test + public void testForeignBlockHandlerClass() throws Exception { + assertThat(fooService.random()).isNotEqualTo(FooUtil.BLOCK_FLAG); + String resourceName = MethodUtil.resolveMethodName(FooService.class.getDeclaredMethod("random")); + ClusterNode cn = ClusterBuilderSlot.getClusterNode(resourceName); + assertThat(cn).isNotNull(); + assertThat(cn.passQps()).isPositive(); + + FlowRuleManager.loadRules(Collections.singletonList( + new FlowRule(resourceName).setCount(0) + )); + assertThat(fooService.random()).isEqualTo(FooUtil.BLOCK_FLAG); + assertThat(cn.blockQps()).isPositive(); + } + + @Test(expected = UndeclaredThrowableException.class) + public void testBlockHandlerNotFound() { + assertThat(fooService.baz("Sentinel")).isEqualTo("cheers, Sentinel"); + String resourceName = "apiBaz"; + ClusterNode cn = ClusterBuilderSlot.getClusterNode(resourceName); + assertThat(cn).isNotNull(); + assertThat(cn.passQps()).isPositive(); + + FlowRuleManager.loadRules(Collections.singletonList( + new FlowRule(resourceName).setCount(0) + )); + fooService.baz("Sentinel"); + } + + @Test + public void testNormalBlockHandlerAndFallback() throws Exception { + assertThat(fooService.foo(1)).isEqualTo("Hello for 1"); + String resourceName = "apiFoo"; + ClusterNode cn = ClusterBuilderSlot.getClusterNode(resourceName); + assertThat(cn).isNotNull(); + assertThat(cn.passQps()).isPositive(); + + // Test for fallback. + assertThat(fooService.foo(9527)).isEqualTo("eee..."); + + // Test for biz exception. + try { + fooService.foo(5758); + fail("should not reach here"); + } catch (IllegalAccessException ex) { + assertThat(cn.exceptionQps()).isPositive(); + } + + // Test for blockHandler + FlowRuleManager.loadRules(Collections.singletonList( + new FlowRule(resourceName).setCount(0) + )); + assertThat(fooService.foo(1121)).isEqualTo("Oops, 1121"); + assertThat(cn.blockQps()).isPositive(); + } + + @Before + public void setUp() throws Exception { + FlowRuleManager.loadRules(new ArrayList()); + ClusterBuilderSlot.resetClusterNodes(); + } + + @After + public void tearDown() throws Exception { + FlowRuleManager.loadRules(new ArrayList()); + ClusterBuilderSlot.resetClusterNodes(); + } +} diff --git a/sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/integration/config/AopTestConfig.java b/sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/integration/config/AopTestConfig.java new file mode 100644 index 00000000..c49bd636 --- /dev/null +++ b/sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/integration/config/AopTestConfig.java @@ -0,0 +1,36 @@ +/* + * 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.annotation.aspectj.integration.config; + +import com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.EnableAspectJAutoProxy; + +/** + * @author Eric Zhao + */ +@Configuration +@EnableAspectJAutoProxy(proxyTargetClass = true) +@ComponentScan("com.alibaba.csp.sentinel.annotation.aspectj.integration") +public class AopTestConfig { + + @Bean + public SentinelResourceAspect sentinelResourceAspect() { + return new SentinelResourceAspect(); + } +} diff --git a/sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/integration/service/FooService.java b/sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/integration/service/FooService.java new file mode 100644 index 00000000..3d30adf6 --- /dev/null +++ b/sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/integration/service/FooService.java @@ -0,0 +1,59 @@ +/* + * 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.annotation.aspectj.integration.service; + +import com.alibaba.csp.sentinel.annotation.SentinelResource; +import com.alibaba.csp.sentinel.slots.block.BlockException; +import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException; +import org.springframework.stereotype.Service; + +import java.util.concurrent.ThreadLocalRandom; + +/** + * @author Eric Zhao + */ +@Service +public class FooService { + + @SentinelResource(value = "apiFoo", blockHandler = "fooBlockHandler", fallback = "fooFallbackFunc") + public String foo(int i) throws Exception { + if (i == 9527) { + throw new DegradeException("ggg"); + } + if (i == 5758) { + throw new IllegalAccessException(); + } + return "Hello for " + i; + } + + @SentinelResource(blockHandler = "globalBlockHandler", blockHandlerClass = FooUtil.class) + public int random() { + return ThreadLocalRandom.current().nextInt(0, 30000); + } + + @SentinelResource(value = "apiBaz", blockHandler = "bazBlockHandler") + public String baz(String name) { + return "cheers, " + name; + } + + public String fooBlockHandler(int i, BlockException ex) { + return "Oops, " + i; + } + + public String fooFallbackFunc(int i) { + return "eee..."; + } +} diff --git a/sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/integration/service/FooUtil.java b/sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/integration/service/FooUtil.java new file mode 100644 index 00000000..52bcb17b --- /dev/null +++ b/sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/integration/service/FooUtil.java @@ -0,0 +1,31 @@ +/* + * 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.annotation.aspectj.integration.service; + +import com.alibaba.csp.sentinel.slots.block.BlockException; + +/** + * @author Eric Zhao + */ +public class FooUtil { + + public static final int BLOCK_FLAG = 88888; + + public static int globalBlockHandler(BlockException ex) { + System.out.println("Oops: " + ex.getClass().getSimpleName()); + return BLOCK_FLAG; + } +}