From 5d3ccb0863b53e3326e78fe47b43acd35a3018d5 Mon Sep 17 00:00:00 2001 From: Jason Joo Date: Wed, 6 Mar 2019 16:49:59 +0800 Subject: [PATCH] Solve the issue that sleeping-based tests are not stable and optimize slow tests (#546) --- pom.xml | 13 +++++ .../sentinel-zuul-adapter/pom.xml | 6 +++ sentinel-core/pom.xml | 8 +++ .../sentinel/AsyncEntryIntegrationTest.java | 6 +-- .../base/metric/MetricsLeapArrayTest.java | 14 ++++-- .../slots/block/degrade/DegradeTest.java | 10 ++-- .../flow/controller/WarmUpControllerTest.java | 7 ++- .../slots/statistic/base/LeapArrayTest.java | 14 ++---- .../sentinel/test/AbstractTimeBasedTest.java | 50 +++++++++++++++++++ 9 files changed, 104 insertions(+), 24 deletions(-) create mode 100644 sentinel-core/src/test/java/com/alibaba/csp/sentinel/test/AbstractTimeBasedTest.java diff --git a/pom.xml b/pom.xml index bf508135..46d22968 100755 --- a/pom.xml +++ b/pom.xml @@ -47,6 +47,7 @@ 4.12 2.21.0 3.1.5 + 2.0.0 UTF-8 @@ -168,6 +169,18 @@ 2.0.0.0 test + + org.powermock + powermock-module-junit4 + ${powermock.version} + test + + + org.powermock + powermock-api-mockito2 + ${powermock.version} + test + diff --git a/sentinel-adapter/sentinel-zuul-adapter/pom.xml b/sentinel-adapter/sentinel-zuul-adapter/pom.xml index 56f469d1..6c7cb43d 100755 --- a/sentinel-adapter/sentinel-zuul-adapter/pom.xml +++ b/sentinel-adapter/sentinel-zuul-adapter/pom.xml @@ -32,6 +32,12 @@ zuul-core ${zuul.version} provided + + + org.mockito + mockito-all + + diff --git a/sentinel-core/pom.xml b/sentinel-core/pom.xml index 186bab62..bb842b3e 100755 --- a/sentinel-core/pom.xml +++ b/sentinel-core/pom.xml @@ -39,6 +39,14 @@ org.hamcrest java-hamcrest + + org.powermock + powermock-module-junit4 + + + org.powermock + powermock-api-mockito2 + diff --git a/sentinel-core/src/test/java/com/alibaba/csp/sentinel/AsyncEntryIntegrationTest.java b/sentinel-core/src/test/java/com/alibaba/csp/sentinel/AsyncEntryIntegrationTest.java index 7da7b39f..0db9d9b7 100644 --- a/sentinel-core/src/test/java/com/alibaba/csp/sentinel/AsyncEntryIntegrationTest.java +++ b/sentinel-core/src/test/java/com/alibaba/csp/sentinel/AsyncEntryIntegrationTest.java @@ -59,7 +59,7 @@ public class AsyncEntryIntegrationTest { @Override public void run() { try { - TimeUnit.SECONDS.sleep(2); + TimeUnit.MILLISECONDS.sleep(500); anotherSyncInAsync(); System.out.println("Async result: 666"); } catch (InterruptedException e) { @@ -178,7 +178,7 @@ public class AsyncEntryIntegrationTest { } // we keep the original timeout of 15 seconds although the test should - // complete in less than 6 seconds + // complete in less than 3 seconds await().timeout(15, TimeUnit.SECONDS) .until(new Callable() { @Override @@ -249,7 +249,7 @@ public class AsyncEntryIntegrationTest { @Override public void run() { try { - TimeUnit.SECONDS.sleep(3); + TimeUnit.MILLISECONDS.sleep(1000); String resp = arg + ": " + System.currentTimeMillis(); handler.accept(resp); diff --git a/sentinel-core/src/test/java/com/alibaba/csp/sentinel/base/metric/MetricsLeapArrayTest.java b/sentinel-core/src/test/java/com/alibaba/csp/sentinel/base/metric/MetricsLeapArrayTest.java index f6f2b29a..18cf7e6f 100755 --- a/sentinel-core/src/test/java/com/alibaba/csp/sentinel/base/metric/MetricsLeapArrayTest.java +++ b/sentinel-core/src/test/java/com/alibaba/csp/sentinel/base/metric/MetricsLeapArrayTest.java @@ -25,6 +25,7 @@ import com.alibaba.csp.sentinel.slots.statistic.data.MetricBucket; import com.alibaba.csp.sentinel.util.TimeUtil; import com.alibaba.csp.sentinel.slots.statistic.base.WindowWrap; import com.alibaba.csp.sentinel.slots.statistic.metric.MetricsLeapArray; +import com.alibaba.csp.sentinel.test.AbstractTimeBasedTest; import org.junit.Test; @@ -35,7 +36,7 @@ import static org.junit.Assert.*; * * @author Eric Zhao */ -public class MetricsLeapArrayTest { +public class MetricsLeapArrayTest extends AbstractTimeBasedTest { private final int windowLengthInMs = 1000; private final int intervalInSec = 2; @@ -149,6 +150,7 @@ public class MetricsLeapArrayTest { @Test public void testGetPreviousWindow() { + setCurrentMillis(System.currentTimeMillis()); MetricsLeapArray leapArray = new MetricsLeapArray(sampleCount, intervalInMs); long time = TimeUtil.currentTimeMillis(); WindowWrap previousWindow = leapArray.currentWindow(time); @@ -166,7 +168,9 @@ public class MetricsLeapArrayTest { final int windowLengthInMs = 100; final int intervalInMs = 1000; final int sampleCount = intervalInMs / windowLengthInMs; - + + setCurrentMillis(System.currentTimeMillis()); + MetricsLeapArray leapArray = new MetricsLeapArray(sampleCount, intervalInMs); long time = TimeUtil.currentTimeMillis(); @@ -180,7 +184,7 @@ public class MetricsLeapArrayTest { assertTrue(windowWraps.contains(wrap)); } - Thread.sleep(windowLengthInMs + intervalInMs); + sleep(windowLengthInMs + intervalInMs); // This will replace the deprecated bucket, so all deprecated buckets will be reset. leapArray.currentWindow(time + windowLengthInMs + intervalInMs).value().addPass(1); @@ -194,7 +198,7 @@ public class MetricsLeapArrayTest { final int intervalInSec = 1; final int intervalInMs = intervalInSec * 1000; final int sampleCount = intervalInMs / windowLengthInMs; - + MetricsLeapArray leapArray = new MetricsLeapArray(sampleCount, intervalInMs); long time = TimeUtil.currentTimeMillis(); @@ -203,7 +207,7 @@ public class MetricsLeapArrayTest { windowWraps.add(leapArray.currentWindow(time)); windowWraps.add(leapArray.currentWindow(time + windowLengthInMs)); - Thread.sleep(intervalInMs + windowLengthInMs * 3); + sleep(intervalInMs + windowLengthInMs * 3); List> list = leapArray.list(); for (WindowWrap wrap : list) { diff --git a/sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/block/degrade/DegradeTest.java b/sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/block/degrade/DegradeTest.java index 76346f5d..faf78931 100755 --- a/sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/block/degrade/DegradeTest.java +++ b/sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/block/degrade/DegradeTest.java @@ -50,7 +50,7 @@ public class DegradeTest { DegradeRule rule = new DegradeRule(); rule.setCount(1); rule.setResource(key); - rule.setTimeWindow(5); + rule.setTimeWindow(2); for (int i = 0; i < 4; i++) { assertTrue(rule.passCheck(context, node, 1)); @@ -61,7 +61,7 @@ public class DegradeTest { assertFalse(rule.passCheck(context, node, 1)); // Restore. - TimeUnit.SECONDS.sleep(6); + TimeUnit.MILLISECONDS.sleep(2200); assertTrue(rule.passCheck(context, node, 1)); } @@ -81,7 +81,7 @@ public class DegradeTest { DegradeRule rule = new DegradeRule(); rule.setCount(0.15); rule.setResource(key); - rule.setTimeWindow(5); + rule.setTimeWindow(2); rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO); when(cn.successQps()).thenReturn(8L); @@ -90,7 +90,7 @@ public class DegradeTest { assertFalse(rule.passCheck(context, node, 1)); // Restore from the degrade timeout. - TimeUnit.SECONDS.sleep(6); + TimeUnit.MILLISECONDS.sleep(2200); when(cn.successQps()).thenReturn(20L); // Will pass. @@ -120,7 +120,7 @@ public class DegradeTest { assertFalse(rule.passCheck(context, node, 1)); // Restore from the degrade timeout. - TimeUnit.SECONDS.sleep(3); + TimeUnit.MILLISECONDS.sleep(2200); when(cn.totalException()).thenReturn(0L); // Will pass. diff --git a/sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/block/flow/controller/WarmUpControllerTest.java b/sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/block/flow/controller/WarmUpControllerTest.java index 6e9f7d08..e91f2a36 100755 --- a/sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/block/flow/controller/WarmUpControllerTest.java +++ b/sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/block/flow/controller/WarmUpControllerTest.java @@ -23,15 +23,18 @@ import static org.mockito.Mockito.when; import org.junit.Test; import com.alibaba.csp.sentinel.node.Node; +import com.alibaba.csp.sentinel.test.AbstractTimeBasedTest; /** * @author jialiang.linjl */ -public class WarmUpControllerTest { +public class WarmUpControllerTest extends AbstractTimeBasedTest { @Test public void testWarmUp() throws InterruptedException { WarmUpController warmupController = new WarmUpController(10, 10, 3); + + setCurrentMillis(System.currentTimeMillis()); Node node = mock(Node.class); @@ -48,7 +51,7 @@ public class WarmUpControllerTest { when(node.previousPassQps()).thenReturn(10L); for (int i = 0; i < 100; i++) { - Thread.sleep(100); + sleep(100); warmupController.canPass(node, 1); } when(node.passQps()).thenReturn(8L); diff --git a/sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/statistic/base/LeapArrayTest.java b/sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/statistic/base/LeapArrayTest.java index 60a7dd8f..ebe821c0 100644 --- a/sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/statistic/base/LeapArrayTest.java +++ b/sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/statistic/base/LeapArrayTest.java @@ -19,13 +19,15 @@ import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; +import com.alibaba.csp.sentinel.test.AbstractTimeBasedTest; + import static org.junit.Assert.*; /** * @author Eric Zhao */ -public class LeapArrayTest { - +public class LeapArrayTest extends AbstractTimeBasedTest { + @Test public void testGetValidHead() { int windowLengthInMs = 100; @@ -44,6 +46,7 @@ public class LeapArrayTest { return windowWrap; } }; + WindowWrap expected1 = leapArray.currentWindow(); expected1.value().addAndGet(1); sleep(windowLengthInMs); @@ -59,11 +62,4 @@ public class LeapArrayTest { assertSame(expected2, leapArray.getValidHead()); } - private void sleep(int t) { - try { - Thread.sleep(t); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } } \ No newline at end of file diff --git a/sentinel-core/src/test/java/com/alibaba/csp/sentinel/test/AbstractTimeBasedTest.java b/sentinel-core/src/test/java/com/alibaba/csp/sentinel/test/AbstractTimeBasedTest.java new file mode 100644 index 00000000..cd7c43dd --- /dev/null +++ b/sentinel-core/src/test/java/com/alibaba/csp/sentinel/test/AbstractTimeBasedTest.java @@ -0,0 +1,50 @@ +/* + * 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 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.util.TimeUtil; + +/** + * 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 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); + } +}