Make build faster by reducing fixed waiting time in tests (#449)

- Apply awaitility to core tests
- Cache maven local repo in Travis
This commit is contained in:
Andres Almiray 2019-01-29 02:57:38 +01:00 committed by Eric Zhao
parent 9e1b5a900b
commit e893dd8c64
13 changed files with 171 additions and 84 deletions

View File

@ -14,3 +14,7 @@ matrix:
after_success: after_success:
- bash <(curl -s https://codecov.io/bash) - bash <(curl -s https://codecov.io/bash)
cache:
directories:
- $HOME/.m2/

13
pom.xml
View File

@ -46,6 +46,7 @@
<!-- Test libs --> <!-- Test libs -->
<junit.version>4.12</junit.version> <junit.version>4.12</junit.version>
<mockito.version>2.21.0</mockito.version> <mockito.version>2.21.0</mockito.version>
<awaitility.version>3.1.5</awaitility.version>
<!-- Build --> <!-- Build -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@ -155,6 +156,18 @@
<version>${mockito.version}</version> <version>${mockito.version}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<version>${awaitility.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>java-hamcrest</artifactId>
<version>2.0.0.0</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>

View File

@ -16,12 +16,28 @@
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<scope>test</scope> <exclusions>
<exclusion>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-libray</artifactId>
</exclusion>
</exclusions>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.mockito</groupId> <groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId> <artifactId>mockito-core</artifactId>
<scope>test</scope> </dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>java-hamcrest</artifactId>
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -15,22 +15,24 @@
*/ */
package com.alibaba.csp.sentinel; package com.alibaba.csp.sentinel;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import com.alibaba.csp.sentinel.context.ContextTestUtil; import com.alibaba.csp.sentinel.context.ContextTestUtil;
import com.alibaba.csp.sentinel.context.ContextUtil; import com.alibaba.csp.sentinel.context.ContextUtil;
import com.alibaba.csp.sentinel.node.DefaultNode; import com.alibaba.csp.sentinel.node.DefaultNode;
import com.alibaba.csp.sentinel.node.Node; import com.alibaba.csp.sentinel.node.Node;
import com.alibaba.csp.sentinel.slots.block.BlockException; import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.hamcrest.CoreMatchers;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import static org.junit.Assert.*; import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import static org.awaitility.Awaitility.await;
import static org.junit.Assert.fail;
/** /**
* Integration test for asynchronous entry, including common scenarios. * Integration test for asynchronous entry, including common scenarios.
@ -175,37 +177,59 @@ public class AsyncEntryIntegrationTest {
ContextUtil.exit(); ContextUtil.exit();
} }
TimeUnit.SECONDS.sleep(15); // we keep the original timeout of 15 seconds although the test should
// complete in less than 6 seconds
await().timeout(15, TimeUnit.SECONDS)
.until(new Callable<DefaultNode>() {
@Override
public DefaultNode call() throws Exception {
return queryInvocationTree(false);
}
}, CoreMatchers.notNullValue());
testInvocationTreeCorrect(); queryInvocationTree(true);
} }
private void testInvocationTreeCorrect() { private DefaultNode queryInvocationTree(boolean check) {
DefaultNode root = Constants.ROOT; DefaultNode root = Constants.ROOT;
DefaultNode entranceNode = shouldHasChildFor(root, contextName); DefaultNode entranceNode = shouldHasChildFor(root, contextName, check);
DefaultNode testTopNode = shouldHasChildFor(entranceNode, "test-top"); DefaultNode testTopNode = shouldHasChildFor(entranceNode, "test-top", check);
DefaultNode testAsyncNode = shouldHasChildFor(testTopNode, "test-async"); DefaultNode testAsyncNode = shouldHasChildFor(testTopNode, "test-async", check);
shouldHasChildFor(testTopNode, "test-sync"); shouldHasChildFor(testTopNode, "test-sync", check);
shouldHasChildFor(testAsyncNode, "test-sync-in-async"); shouldHasChildFor(testAsyncNode, "test-sync-in-async", check);
DefaultNode anotherAsyncInAsyncNode = shouldHasChildFor(testAsyncNode, "test-another-async"); DefaultNode anotherAsyncInAsyncNode = shouldHasChildFor(testAsyncNode, "test-another-async", check);
shouldHasChildFor(anotherAsyncInAsyncNode, "test-another-in-async"); return shouldHasChildFor(anotherAsyncInAsyncNode, "test-another-in-async", check);
} }
private DefaultNode shouldHasChildFor(DefaultNode root, String resourceName) { private DefaultNode shouldHasChildFor(DefaultNode root, String resourceName, boolean check) {
if (root == null) {
if (check) {
fail("Root node should not be empty");
} else {
return null;
}
}
Set<Node> nodeSet = root.getChildList(); Set<Node> nodeSet = root.getChildList();
if (nodeSet == null || nodeSet.isEmpty()) { if (nodeSet == null || nodeSet.isEmpty()) {
if (check) {
fail("Child nodes should not be empty: " + root.getId().getName()); fail("Child nodes should not be empty: " + root.getId().getName());
} else {
return null;
}
} }
for (Node node : nodeSet) { for (Node node : nodeSet) {
if (node instanceof DefaultNode) { if (node instanceof DefaultNode) {
DefaultNode dn = (DefaultNode)node; DefaultNode dn = (DefaultNode) node;
if (dn.getId().getName().equals(resourceName)) { if (dn.getId().getName().equals(resourceName)) {
return dn; return dn;
} }
} }
} }
if (check) {
fail(String.format("The given node <%s> does not have child for resource <%s>", fail(String.format("The given node <%s> does not have child for resource <%s>",
root.getId().getName(), resourceName)); root.getId().getName(), resourceName));
}
return null; return null;
} }

View File

@ -203,7 +203,7 @@ public class MetricsLeapArrayTest {
windowWraps.add(leapArray.currentWindow(time)); windowWraps.add(leapArray.currentWindow(time));
windowWraps.add(leapArray.currentWindow(time + windowLengthInMs)); windowWraps.add(leapArray.currentWindow(time + windowLengthInMs));
Thread.sleep(intervalInSec * 1000 + windowLengthInMs * 3); Thread.sleep(intervalInMs + windowLengthInMs * 3);
List<WindowWrap<MetricBucket>> list = leapArray.list(); List<WindowWrap<MetricBucket>> list = leapArray.list();
for (WindowWrap<MetricBucket> wrap : list) { for (WindowWrap<MetricBucket> wrap : list) {

View File

@ -16,6 +16,7 @@
package com.alibaba.csp.sentinel.slots.block.flow; package com.alibaba.csp.sentinel.slots.block.flow;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
@ -57,8 +58,8 @@ public class FlowPartialIntegrationTest {
} }
} }
@Test @Test(expected = BlockException.class)
public void testThreadGrade() throws InterruptedException { public void testThreadGrade() throws InterruptedException, BlockException {
FlowRule flowRule = new FlowRule(); FlowRule flowRule = new FlowRule();
flowRule.setResource("testThreadGrade"); flowRule.setResource("testThreadGrade");
flowRule.setGrade(RuleConstant.FLOW_GRADE_THREAD); flowRule.setGrade(RuleConstant.FLOW_GRADE_THREAD);
@ -73,17 +74,15 @@ public class FlowPartialIntegrationTest {
Entry e = null; Entry e = null;
try { try {
e = SphU.entry("testThreadGrade"); e = SphU.entry("testThreadGrade");
assertTrue(true);
synchronized (sequence) { synchronized (sequence) {
System.out.println("notify up"); System.out.println("notify up");
sequence.notify(); sequence.notify();
} }
Thread.sleep(1000); Thread.sleep(100);
} catch (BlockException e1) { } catch (BlockException e1) {
assertTrue(false); fail("Should had failed");
} catch (InterruptedException e1) { } catch (InterruptedException e1) {
assertTrue(false); fail("Should had failed");
e1.printStackTrace();
} }
e.exit(); e.exit();
} }
@ -92,20 +91,14 @@ public class FlowPartialIntegrationTest {
Thread thread = new Thread(runnable); Thread thread = new Thread(runnable);
thread.start(); thread.start();
Entry e = null;
synchronized (sequence) { synchronized (sequence) {
System.out.println("sleep"); System.out.println("sleep");
sequence.wait(); sequence.wait();
System.out.println("wake up"); System.out.println("wake up");
} }
try {
e = SphU.entry("testThreadGrade");
assertTrue(false);
} catch (BlockException e1) {
assertTrue(true);
}
System.out.println("done");
SphU.entry("testThreadGrade");
System.out.println("done");
} }
@Test @Test
@ -129,10 +122,9 @@ public class FlowPartialIntegrationTest {
Entry e = null; Entry e = null;
try { try {
e = SphU.entry("testOriginFlowRule"); e = SphU.entry("testOriginFlowRule");
assertTrue(false); fail("Should had failed");
} catch (BlockException e1) { } catch (BlockException e1) {
e1.printStackTrace(); e1.printStackTrace();
assertTrue(true);
} }
assertTrue(e == null); assertTrue(e == null);
@ -142,10 +134,8 @@ public class FlowPartialIntegrationTest {
e = null; e = null;
try { try {
e = SphU.entry("testOriginFlowRule"); e = SphU.entry("testOriginFlowRule");
assertTrue(true);
} catch (BlockException e1) { } catch (BlockException e1) {
e1.printStackTrace(); fail("Should had failed");
assertTrue(false);
} }
e.exit(); e.exit();
@ -165,17 +155,14 @@ public class FlowPartialIntegrationTest {
Entry e = null; Entry e = null;
try { try {
e = SphU.entry("testOther"); e = SphU.entry("testOther");
assertTrue(true);
} catch (BlockException e1) { } catch (BlockException e1) {
e1.printStackTrace(); e1.printStackTrace();fail("Should had failed");
assertTrue(false);
} }
if (e != null) { if (e != null) {
assertTrue(true);
e.exit(); e.exit();
} else { } else {
assertTrue(false); fail("Should had failed");
} }
} }
@ -194,10 +181,9 @@ public class FlowPartialIntegrationTest {
Entry e = null; Entry e = null;
try { try {
e = SphU.entry("testStrategy"); e = SphU.entry("testStrategy");
assertTrue(false); fail("Should had failed");
} catch (BlockException e1) { } catch (BlockException e1) {
e1.printStackTrace(); e1.printStackTrace();
assertTrue(true);
} }
ContextUtil.exit(); ContextUtil.exit();
@ -215,10 +201,9 @@ public class FlowPartialIntegrationTest {
ContextUtil.enter("entry1"); ContextUtil.enter("entry1");
try { try {
e = SphU.entry("testStrategy"); e = SphU.entry("testStrategy");
assertTrue(true);
} catch (BlockException e1) { } catch (BlockException e1) {
e1.printStackTrace(); e1.printStackTrace();
assertTrue(false); fail("Should had failed");
} }
e.exit(); e.exit();
ContextUtil.exit(); ContextUtil.exit();
@ -238,10 +223,9 @@ public class FlowPartialIntegrationTest {
ContextUtil.enter("entry1"); ContextUtil.enter("entry1");
try { try {
e = SphU.entry("entry2"); e = SphU.entry("entry2");
assertTrue(false); fail("Should had failed");
} catch (BlockException e1) { } catch (BlockException e1) {
e1.printStackTrace(); e1.printStackTrace();
assertTrue(true);
} }
ContextUtil.exit(); ContextUtil.exit();
@ -250,13 +234,11 @@ public class FlowPartialIntegrationTest {
ContextUtil.enter("entry3"); ContextUtil.enter("entry3");
try { try {
e = SphU.entry("entry2"); e = SphU.entry("entry2");
assertTrue(true);
} catch (BlockException e1) { } catch (BlockException e1) {
assertTrue(false); fail("Should had failed");
} }
e.exit(); e.exit();
ContextUtil.exit(); ContextUtil.exit();
} }
} }

View File

@ -23,7 +23,6 @@ import static org.mockito.Mockito.when;
import org.junit.Test; import org.junit.Test;
import com.alibaba.csp.sentinel.node.Node; import com.alibaba.csp.sentinel.node.Node;
import com.alibaba.csp.sentinel.slots.block.flow.controller.WarmUpController;
/** /**
* @author jialiang.linjl * @author jialiang.linjl
@ -49,7 +48,7 @@ public class WarmUpControllerTest {
when(node.previousPassQps()).thenReturn(10L); when(node.previousPassQps()).thenReturn(10L);
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
Thread.sleep(1000); Thread.sleep(100);
warmupController.canPass(node, 1); warmupController.canPass(node, 1);
} }
when(node.passQps()).thenReturn(8L); when(node.passQps()).thenReturn(8L);

View File

@ -1,12 +1,18 @@
package com.alibaba.csp.sentinel.slots.logger; package com.alibaba.csp.sentinel.slots.logger;
import java.io.File; import java.io.File;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import com.alibaba.csp.sentinel.log.LogBase; import com.alibaba.csp.sentinel.log.LogBase;
import com.alibaba.csp.sentinel.log.RecordLog; import com.alibaba.csp.sentinel.log.RecordLog;
import org.hamcrest.CoreMatchers;
import org.hamcrest.Matchers;
import org.hamcrest.io.FileMatchers;
import org.junit.Test; import org.junit.Test;
import static org.awaitility.Awaitility.await;
import static org.junit.Assert.*; import static org.junit.Assert.*;
/** /**
@ -17,9 +23,15 @@ public class EagleEyeLogUtilTest {
@Test @Test
public void testWriteLog() throws Exception { public void testWriteLog() throws Exception {
EagleEyeLogUtil.log("resourceName", "BlockException", "app1", "origin", 1); EagleEyeLogUtil.log("resourceName", "BlockException", "app1", "origin", 1);
Thread.sleep(1100);
String file = RecordLog.getLogBaseDir() + EagleEyeLogUtil.FILE_NAME; final File file = new File(RecordLog.getLogBaseDir() + EagleEyeLogUtil.FILE_NAME);
assertTrue(new File(file).exists()); await().timeout(2, TimeUnit.SECONDS)
.until(new Callable<File>() {
@Override
public File call() throws Exception {
return file;
}
}, FileMatchers.anExistingFile());
} }
@Test @Test
@ -29,8 +41,14 @@ public class EagleEyeLogUtilTest {
System.setProperty(LogBase.LOG_DIR, newLogBase); System.setProperty(LogBase.LOG_DIR, newLogBase);
EagleEyeLogUtil.log("resourceName", "BlockException", "app1", "origin", 1); EagleEyeLogUtil.log("resourceName", "BlockException", "app1", "origin", 1);
Thread.sleep(1100);
String file = RecordLog.getLogBaseDir() + EagleEyeLogUtil.FILE_NAME; final File file = new File(RecordLog.getLogBaseDir() + EagleEyeLogUtil.FILE_NAME);
assertTrue(new File(file).exists()); await().timeout(2, TimeUnit.SECONDS)
.until(new Callable<File>() {
@Override
public File call() throws Exception {
return file;
}
}, FileMatchers.anExistingFile());
} }
} }

View File

@ -34,7 +34,10 @@
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<scope>test</scope> </dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.alibaba</groupId> <groupId>com.alibaba</groupId>

View File

@ -27,10 +27,15 @@ import com.alibaba.fastjson.TypeReference;
import io.lettuce.core.RedisClient; import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisURI; import io.lettuce.core.RedisURI;
import io.lettuce.core.api.sync.RedisCommands; import io.lettuce.core.api.sync.RedisCommands;
import org.hamcrest.Matchers;
import org.junit.*; import org.junit.*;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import static org.awaitility.Awaitility.await;
/** /**
* Redis redisSentinel mode test cases for {@link RedisDataSource}. * Redis redisSentinel mode test cases for {@link RedisDataSource}.
@ -79,14 +84,16 @@ public class SentinelModeRedisDataSourceTest {
subCommands.set(ruleKey, flowRulesJson); subCommands.set(ruleKey, flowRulesJson);
subCommands.publish(channel, flowRulesJson); subCommands.publish(channel, flowRulesJson);
subCommands.exec(); subCommands.exec();
try {
Thread.sleep(2000); await().timeout(2, TimeUnit.SECONDS)
} catch (InterruptedException e) { .until(new Callable<List<FlowRule>>() {
e.printStackTrace(); @Override
public List<FlowRule> call() throws Exception {
return FlowRuleManager.getRules();
} }
}, Matchers.hasSize(1));
List<FlowRule> rules = FlowRuleManager.getRules(); List<FlowRule> rules = FlowRuleManager.getRules();
Assert.assertEquals(1, rules.size());
rules = FlowRuleManager.getRules();
Assert.assertEquals(rules.get(0).getMaxQueueingTimeMs(), maxQueueingTimeMs); Assert.assertEquals(rules.get(0).getMaxQueueingTimeMs(), maxQueueingTimeMs);
String value = subCommands.get(ruleKey); String value = subCommands.get(ruleKey);
List<FlowRule> flowRulesValuesInRedis = buildFlowConfigParser().convert(value); List<FlowRule> flowRulesValuesInRedis = buildFlowConfigParser().convert(value);

View File

@ -31,6 +31,7 @@ import io.lettuce.core.RedisURI;
import io.lettuce.core.api.sync.RedisCommands; import io.lettuce.core.api.sync.RedisCommands;
import io.lettuce.core.pubsub.StatefulRedisPubSubConnection; import io.lettuce.core.pubsub.StatefulRedisPubSubConnection;
import io.lettuce.core.pubsub.api.sync.RedisPubSubCommands; import io.lettuce.core.pubsub.api.sync.RedisPubSubCommands;
import org.hamcrest.Matchers;
import org.junit.After; import org.junit.After;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
@ -39,6 +40,10 @@ import org.junit.Test;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import static org.awaitility.Awaitility.await;
/** /**
* Redis stand-alone mode test cases for {@link RedisDataSource}. * Redis stand-alone mode test cases for {@link RedisDataSource}.
@ -92,11 +97,15 @@ public class StandaloneRedisDataSourceTest {
subCommands.set(ruleKey, flowRules); subCommands.set(ruleKey, flowRules);
subCommands.publish(channel, flowRules); subCommands.publish(channel, flowRules);
subCommands.exec(); subCommands.exec();
try {
Thread.sleep(2000); await().timeout(2, TimeUnit.SECONDS)
} catch (InterruptedException e) { .until(new Callable<List<FlowRule>>() {
e.printStackTrace(); @Override
public List<FlowRule> call() throws Exception {
return FlowRuleManager.getRules();
} }
}, Matchers.hasSize(1));
rules = FlowRuleManager.getRules(); rules = FlowRuleManager.getRules();
Assert.assertEquals(rules.get(0).getMaxQueueingTimeMs(), maxQueueingTimeMs); Assert.assertEquals(rules.get(0).getMaxQueueingTimeMs(), maxQueueingTimeMs);
String value = subCommands.get(ruleKey); String value = subCommands.get(ruleKey);

View File

@ -46,7 +46,10 @@
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<scope>test</scope> </dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.curator</groupId> <groupId>org.apache.curator</groupId>

View File

@ -2,6 +2,8 @@ package com.alibaba.csp.sentinel.datasource.zookeeper;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import com.alibaba.csp.sentinel.datasource.Converter; import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.datasource.ReadableDataSource; import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
@ -19,6 +21,7 @@ import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat; import org.apache.zookeeper.data.Stat;
import org.junit.Test; import org.junit.Test;
import static org.awaitility.Awaitility.await;
import static org.junit.Assert.*; import static org.junit.Assert.*;
/** /**
@ -68,10 +71,16 @@ public class ZookeeperDataSourceTest {
String ruleString = JSON.toJSONString(Collections.singletonList(rule)); String ruleString = JSON.toJSONString(Collections.singletonList(rule));
zkClient.setData().forPath(path, ruleString.getBytes()); zkClient.setData().forPath(path, ruleString.getBytes());
Thread.sleep(5000); await().timeout(5, TimeUnit.SECONDS)
.until(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
List<FlowRule> rules = FlowRuleManager.getRules();
return rules != null && !rules.isEmpty();
}
});
List<FlowRule> rules = FlowRuleManager.getRules(); List<FlowRule> rules = FlowRuleManager.getRules();
assertTrue(rules != null && !rules.isEmpty());
boolean exists = false; boolean exists = false;
for (FlowRule r : rules) { for (FlowRule r : rules) {
if (resourceName.equals(r.getResource())) { if (resourceName.equals(r.getResource())) {