mirror of
https://gitee.com/dromara/liteFlow.git
synced 2026-05-14 12:12:08 +08:00
feature 超时时间支持毫秒 no spring UT
This commit is contained in:
@@ -0,0 +1,202 @@
|
|||||||
|
package com.yomahub.liteflow.test.maxWaitMilliseconds;
|
||||||
|
|
||||||
|
import com.yomahub.liteflow.builder.LiteFlowNodeBuilder;
|
||||||
|
import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder;
|
||||||
|
import com.yomahub.liteflow.core.FlowExecutor;
|
||||||
|
import com.yomahub.liteflow.core.FlowExecutorHolder;
|
||||||
|
import com.yomahub.liteflow.enums.NodeTypeEnum;
|
||||||
|
import com.yomahub.liteflow.exception.WhenTimeoutException;
|
||||||
|
import com.yomahub.liteflow.flow.LiteflowResponse;
|
||||||
|
import com.yomahub.liteflow.property.LiteflowConfig;
|
||||||
|
import com.yomahub.liteflow.slot.DefaultContext;
|
||||||
|
import com.yomahub.liteflow.test.BaseTest;
|
||||||
|
import com.yomahub.liteflow.test.maxWaitSeconds.cmp.ACmp;
|
||||||
|
import com.yomahub.liteflow.test.maxWaitSeconds.cmp.BCmp;
|
||||||
|
import com.yomahub.liteflow.test.maxWaitSeconds.cmp.CCmp;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
|
import static com.yomahub.liteflow.test.maxWaitSeconds.cmp.DCmp.CONTENT_KEY;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 非 Spring 环境下超时控制测试
|
||||||
|
*
|
||||||
|
* @author Kugaaa
|
||||||
|
* @since 2.11.1
|
||||||
|
*/
|
||||||
|
public class MaxWaitMillisecondsTest extends BaseTest {
|
||||||
|
|
||||||
|
private static FlowExecutor flowExecutor;
|
||||||
|
|
||||||
|
@BeforeAll
|
||||||
|
public static void init() {
|
||||||
|
LiteflowConfig config = new LiteflowConfig();
|
||||||
|
config.setRuleSource("maxWaitMilliseconds/flow.el.xml");
|
||||||
|
flowExecutor = FlowExecutorHolder.loadInstance(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试 THEN 的超时情况
|
||||||
|
@Test
|
||||||
|
public void testThen1() {
|
||||||
|
assertTimeout("then1");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试 THEN 的非超时情况
|
||||||
|
@Test
|
||||||
|
public void testThen2() {
|
||||||
|
assertNotTimeout("then2");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试 When 的超时情况
|
||||||
|
@Test
|
||||||
|
public void testWhen1() {
|
||||||
|
assertWhenTimeout("when1");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试 WHEN 的非超时情况
|
||||||
|
@Test
|
||||||
|
public void testWhen2() {
|
||||||
|
assertNotTimeout("when2");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试 FOR 的超时情况
|
||||||
|
@Test
|
||||||
|
public void testFor1() {
|
||||||
|
assertTimeout("for1");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试 FOR 的非超时情况
|
||||||
|
@Test
|
||||||
|
public void testFor2() {
|
||||||
|
assertNotTimeout("for2");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试 WHILE 的超时情况
|
||||||
|
@Test
|
||||||
|
public void testWhile1() {
|
||||||
|
assertTimeout("while1");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试 WHILE 的非超时情况
|
||||||
|
@Test
|
||||||
|
public void testWhile2() {
|
||||||
|
assertNotTimeout("while2");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试 ITERATOR 的超时情况
|
||||||
|
@Test
|
||||||
|
public void testIterator1() {
|
||||||
|
assertTimeout("iterator1");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试 ITERATOR 的非超时情况
|
||||||
|
@Test
|
||||||
|
public void testIterator2() {
|
||||||
|
assertNotTimeout("iterator2");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试 SWITCH 的超时情况
|
||||||
|
@Test
|
||||||
|
public void testSwitch1() {
|
||||||
|
assertTimeout("switch1");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试 SWITCH 的非超时情况
|
||||||
|
@Test
|
||||||
|
public void testSwitch2() {
|
||||||
|
assertNotTimeout("switch2");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试 IF 的超时情况
|
||||||
|
@Test
|
||||||
|
public void testIf1() {
|
||||||
|
assertTimeout("if1");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试 SWITCH 的非超时情况
|
||||||
|
@Test
|
||||||
|
public void testIf2() {
|
||||||
|
assertNotTimeout("if2");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试单个组件的超时情况
|
||||||
|
@Test
|
||||||
|
public void testComponent1() {
|
||||||
|
assertTimeout("component1");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试单个组件的非超时情况
|
||||||
|
@Test
|
||||||
|
public void testComponent2() {
|
||||||
|
assertNotTimeout("component2");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试 FINALLY,虽然超时,但 FINALLY 仍会执行
|
||||||
|
@Test
|
||||||
|
public void testFinally1() {
|
||||||
|
LiteflowResponse response = flowExecutor.execute2Resp("finally", "arg");
|
||||||
|
Assertions.assertFalse(response.isSuccess());
|
||||||
|
Assertions.assertEquals(TimeoutException.class, response.getCause().getClass());
|
||||||
|
// FINALLY 执行时在默认数据上下文中放入了 CONTENT_KEY
|
||||||
|
DefaultContext contextBean = response.getFirstContextBean();
|
||||||
|
Assertions.assertTrue(contextBean.hasData(CONTENT_KEY));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试 maxWaitMilliseconds 关键字不能作用于 Finally
|
||||||
|
@Test
|
||||||
|
public void testFinally2() {
|
||||||
|
LiteFlowNodeBuilder.createNode()
|
||||||
|
.setId("a")
|
||||||
|
.setName("组件A")
|
||||||
|
.setType(NodeTypeEnum.COMMON)
|
||||||
|
.setClazz(ACmp.class)
|
||||||
|
.build();
|
||||||
|
LiteFlowNodeBuilder.createNode()
|
||||||
|
.setId("b")
|
||||||
|
.setName("组件B")
|
||||||
|
.setType(NodeTypeEnum.COMMON)
|
||||||
|
.setClazz(BCmp.class)
|
||||||
|
.build();
|
||||||
|
LiteFlowNodeBuilder.createNode()
|
||||||
|
.setId("c")
|
||||||
|
.setName("组件C")
|
||||||
|
.setType(NodeTypeEnum.COMMON)
|
||||||
|
.setClazz(CCmp.class)
|
||||||
|
.build();
|
||||||
|
Assertions.assertFalse(LiteFlowChainELBuilder.validate("THEN(a, b, FINALLY(c).maxWaitMilliseconds(100))"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试 chain 的超时情况
|
||||||
|
@Test
|
||||||
|
public void testChain1() {
|
||||||
|
assertTimeout("chain1");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试 chain 的非超时情况
|
||||||
|
@Test
|
||||||
|
public void testChain2() {
|
||||||
|
assertNotTimeout("chain2");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertTimeout(String chainId) {
|
||||||
|
LiteflowResponse response = flowExecutor.execute2Resp(chainId, "arg");
|
||||||
|
Assertions.assertFalse(response.isSuccess());
|
||||||
|
Assertions.assertEquals(TimeoutException.class, response.getCause().getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertWhenTimeout(String chainId) {
|
||||||
|
LiteflowResponse response = flowExecutor.execute2Resp(chainId, "arg");
|
||||||
|
Assertions.assertFalse(response.isSuccess());
|
||||||
|
Assertions.assertEquals(WhenTimeoutException.class, response.getCause().getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertNotTimeout(String chainId) {
|
||||||
|
LiteflowResponse response = flowExecutor.execute2Resp(chainId, "arg");
|
||||||
|
Assertions.assertTrue(response.isSuccess());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp;
|
||||||
|
|
||||||
|
import com.yomahub.liteflow.core.NodeComponent;
|
||||||
|
|
||||||
|
public class ACmp extends NodeComponent {
|
||||||
|
@Override
|
||||||
|
public void process() {
|
||||||
|
try {
|
||||||
|
Thread.sleep(100);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("ACmp executed!");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp;
|
||||||
|
|
||||||
|
import com.yomahub.liteflow.core.NodeComponent;
|
||||||
|
|
||||||
|
public class BCmp extends NodeComponent {
|
||||||
|
@Override
|
||||||
|
public void process() {
|
||||||
|
try {
|
||||||
|
Thread.sleep(200);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("BCmp executed!");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp;
|
||||||
|
|
||||||
|
import com.yomahub.liteflow.core.NodeComponent;
|
||||||
|
|
||||||
|
public class CCmp extends NodeComponent {
|
||||||
|
@Override
|
||||||
|
public void process() {
|
||||||
|
try {
|
||||||
|
Thread.sleep(500);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("CCmp executed!");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp;
|
||||||
|
|
||||||
|
import com.yomahub.liteflow.core.NodeComponent;
|
||||||
|
import com.yomahub.liteflow.slot.DefaultContext;
|
||||||
|
|
||||||
|
|
||||||
|
public class DCmp extends NodeComponent {
|
||||||
|
|
||||||
|
public static final String CONTENT_KEY = "testKey";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process() {
|
||||||
|
try {
|
||||||
|
Thread.sleep(500);
|
||||||
|
DefaultContext contextBean = this.getFirstContextBean();
|
||||||
|
contextBean.setData(CONTENT_KEY, "value");
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("DCmp executed!");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp;
|
||||||
|
|
||||||
|
import com.yomahub.liteflow.core.NodeIfComponent;
|
||||||
|
|
||||||
|
public class FCmp extends NodeIfComponent {
|
||||||
|
@Override
|
||||||
|
public boolean processIf() throws Exception {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp;
|
||||||
|
|
||||||
|
import com.yomahub.liteflow.core.NodeSwitchComponent;
|
||||||
|
|
||||||
|
public class SCmp extends NodeSwitchComponent {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String processSwitch() throws Exception {
|
||||||
|
return "b";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp;
|
||||||
|
|
||||||
|
import com.yomahub.liteflow.core.NodeWhileComponent;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class WCmp extends NodeWhileComponent {
|
||||||
|
private int count = 0;
|
||||||
|
|
||||||
|
// 执行过的 chain
|
||||||
|
Set<String> executedChain = new HashSet<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean processWhile() throws Exception {
|
||||||
|
// 判断是否切换了 chain
|
||||||
|
if (!executedChain.contains(this.getCurrChainId())) {
|
||||||
|
count = 0;
|
||||||
|
executedChain.add(this.getCurrChainId());
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
return count <= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.ListUtil;
|
||||||
|
import com.yomahub.liteflow.core.NodeIteratorComponent;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class XCmp extends NodeIteratorComponent {
|
||||||
|
@Override
|
||||||
|
public Iterator<?> processIterator() throws Exception {
|
||||||
|
List<String> list = ListUtil.toList("one", "two");
|
||||||
|
return list.iterator();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<flow>
|
||||||
|
<nodes>
|
||||||
|
<node id="a" class="com.yomahub.liteflow.test.maxWaitMilliseconds.cmp.ACmp"/>
|
||||||
|
<node id="b" class="com.yomahub.liteflow.test.maxWaitMilliseconds.cmp.BCmp"/>
|
||||||
|
<node id="c" class="com.yomahub.liteflow.test.maxWaitMilliseconds.cmp.CCmp"/>
|
||||||
|
<node id="d" class="com.yomahub.liteflow.test.maxWaitMilliseconds.cmp.DCmp"/>
|
||||||
|
<node id="f" class="com.yomahub.liteflow.test.maxWaitMilliseconds.cmp.FCmp"/>
|
||||||
|
<node id="s" class="com.yomahub.liteflow.test.maxWaitMilliseconds.cmp.SCmp"/>
|
||||||
|
<node id="w" class="com.yomahub.liteflow.test.maxWaitMilliseconds.cmp.WCmp"/>
|
||||||
|
<node id="x" class="com.yomahub.liteflow.test.maxWaitMilliseconds.cmp.XCmp"/>
|
||||||
|
</nodes>
|
||||||
|
<!--
|
||||||
|
a=>1s b=>2s c=>5s
|
||||||
|
-->
|
||||||
|
<!-- 串行编排测试 -->
|
||||||
|
<chain name="then1">
|
||||||
|
<!-- 超时 -->
|
||||||
|
THEN(a,b).maxWaitMilliseconds(200);
|
||||||
|
</chain>
|
||||||
|
<chain name="then2">
|
||||||
|
<!-- 不超时 -->
|
||||||
|
THEN(a,b).maxWaitMilliseconds(500);
|
||||||
|
</chain>
|
||||||
|
|
||||||
|
<!-- 并行编排测试 -->
|
||||||
|
<chain name="when1">
|
||||||
|
<!-- 超时 -->
|
||||||
|
WHEN(a,c).maxWaitMilliseconds(300);
|
||||||
|
</chain>
|
||||||
|
<chain name="when2">
|
||||||
|
<!-- 不超时 -->
|
||||||
|
WHEN(a,b).maxWaitMilliseconds(300);
|
||||||
|
</chain>
|
||||||
|
|
||||||
|
<!-- 循环编排测试 -->
|
||||||
|
<chain name="for1">
|
||||||
|
<!-- 超时 -->
|
||||||
|
FOR(2).DO(a).maxWaitMilliseconds(100);
|
||||||
|
</chain>
|
||||||
|
<chain name="for2">
|
||||||
|
<!-- 不超时 -->
|
||||||
|
FOR(2).DO(a).maxWaitMilliseconds(300);
|
||||||
|
</chain>
|
||||||
|
<!-- w 循环两次 -->
|
||||||
|
<chain name="while1">
|
||||||
|
<!-- 超时 -->
|
||||||
|
WHILE(w).DO(a).maxWaitMilliseconds(100);
|
||||||
|
</chain>
|
||||||
|
<chain name="while2">
|
||||||
|
<!-- 不超时 -->
|
||||||
|
WHILE(w).DO(a).maxWaitMilliseconds(300);
|
||||||
|
</chain>
|
||||||
|
<!-- x 迭代两次 -->
|
||||||
|
<chain name="iterator1">
|
||||||
|
<!-- 超时 -->
|
||||||
|
ITERATOR(x).DO(a).maxWaitMilliseconds(100);
|
||||||
|
</chain>
|
||||||
|
<chain name="iterator2">
|
||||||
|
<!-- 不超时 -->
|
||||||
|
ITERATOR(x).DO(a).maxWaitMilliseconds(300);
|
||||||
|
</chain>
|
||||||
|
|
||||||
|
<!-- 选择编排测试 -->
|
||||||
|
<!-- s 选择 b 组件 -->
|
||||||
|
<chain name="switch1">
|
||||||
|
<!-- 超时 -->
|
||||||
|
SWITCH(s).TO(a, b).maxWaitMilliseconds(100);
|
||||||
|
</chain>
|
||||||
|
<chain name="switch2">
|
||||||
|
<!-- 不超时 -->
|
||||||
|
SWITCH(s).TO(a, b).maxWaitMilliseconds(300);
|
||||||
|
</chain>
|
||||||
|
|
||||||
|
<!-- 条件编排测试 -->
|
||||||
|
<!-- f 返回 true -->
|
||||||
|
<chain name="if1">
|
||||||
|
<!-- 超时 -->
|
||||||
|
IF(f, b, c).maxWaitMilliseconds(100);
|
||||||
|
</chain>
|
||||||
|
<chain name="if2">
|
||||||
|
<!-- 不超时 -->
|
||||||
|
IF(f, b, c).maxWaitMilliseconds(300);
|
||||||
|
</chain>
|
||||||
|
|
||||||
|
<!-- 测试单个组件 -->
|
||||||
|
<chain name="component1">
|
||||||
|
<!-- 超时 -->
|
||||||
|
WHEN(
|
||||||
|
a.maxWaitMilliseconds(200),
|
||||||
|
c.maxWaitMilliseconds(300)
|
||||||
|
);
|
||||||
|
</chain>
|
||||||
|
<chain name="component2">
|
||||||
|
<!-- 不超时 -->
|
||||||
|
WHEN(
|
||||||
|
a.maxWaitMilliseconds(200),
|
||||||
|
b.maxWaitMilliseconds(300)
|
||||||
|
);
|
||||||
|
</chain>
|
||||||
|
|
||||||
|
<!-- 测试 FINALLY -->
|
||||||
|
<chain name="finally">
|
||||||
|
<!-- 超时,但 FINALLY 执行 -->
|
||||||
|
THEN(PRE(a), b, FINALLY(d)).maxWaitMilliseconds(200);
|
||||||
|
</chain>
|
||||||
|
|
||||||
|
<!-- 测试 chain -->
|
||||||
|
<chain name="testChain">
|
||||||
|
THEN(b)
|
||||||
|
</chain>
|
||||||
|
<chain name="chain1">
|
||||||
|
<!-- 超时 -->
|
||||||
|
testChain.maxWaitMilliseconds(100);
|
||||||
|
</chain>
|
||||||
|
<chain name="chain2">
|
||||||
|
<!-- 不超时 -->
|
||||||
|
testChain.maxWaitMilliseconds(300);
|
||||||
|
</chain>
|
||||||
|
</flow>
|
||||||
Reference in New Issue
Block a user