feature 超时时间支持毫秒 decl springboot UT

This commit is contained in:
Kugaaa 2023-11-03 14:59:08 +08:00
parent 0ed020d498
commit 88b031c647
11 changed files with 494 additions and 0 deletions

View File

@ -0,0 +1,204 @@
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.enums.NodeTypeEnum;
import com.yomahub.liteflow.exception.WhenTimeoutException;
import com.yomahub.liteflow.flow.LiteflowResponse;
import com.yomahub.liteflow.slot.DefaultContext;
import com.yomahub.liteflow.test.BaseTest;
import com.yomahub.liteflow.test.maxWaitMilliseconds.cmp.ACmp;
import com.yomahub.liteflow.test.maxWaitMilliseconds.cmp.BCmp;
import com.yomahub.liteflow.test.maxWaitMilliseconds.cmp.CCmp;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import javax.annotation.Resource;
import java.util.concurrent.TimeoutException;
import static com.yomahub.liteflow.test.maxWaitSeconds.cmp.DCmp.CONTENT_KEY;
/**
* Spring Boot 环境下超时控制测试 - maxWaitMilliseconds
*
* @author Kugaaa
* @since 2.11.1
*/
@ExtendWith(SpringExtension.class)
@TestPropertySource(value = "classpath:/maxWaitMilliseconds/application.properties")
@SpringBootTest(classes = MaxWaitMillisecondsELDeclSpringbootTest.class)
@EnableAutoConfiguration
@ComponentScan({"com.yomahub.liteflow.test.maxWaitMilliseconds.cmp"})
public class MaxWaitMillisecondsELDeclSpringbootTest extends BaseTest {
@Resource
private FlowExecutor flowExecutor;
// 测试 THEN 的超时情况
@Test
public void testThen1() {
assertTimeout("then1");
}
// 测试 THEN 的非超时情况
@Test
public void testThen2() {
assertNotTimeout("then2");
}
// 测试 When 的超时情况
@Test
public void testWhen1() {
// WHEN 抛出的是 WhenTimeoutException
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());
}
}

View File

@ -0,0 +1,21 @@
package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
@LiteflowComponent("a")
public class ACmp {
@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
public void process(NodeComponent bindCmp) {
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("ACmp executed!");
}
}

View File

@ -0,0 +1,21 @@
package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
@LiteflowComponent("b")
public class BCmp {
@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
public void process(NodeComponent bindCmp) {
try {
Thread.sleep(200);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("BCmp executed!");
}
}

View File

@ -0,0 +1,21 @@
package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
@LiteflowComponent("c")
public class CCmp {
@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
public void process(NodeComponent bindCmp) {
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("CCmp executed!");
}
}

View File

@ -0,0 +1,26 @@
package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import com.yomahub.liteflow.slot.DefaultContext;
@LiteflowComponent("d")
public class DCmp {
public static final String CONTENT_KEY = "testKey";
@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
public void process(NodeComponent bindCmp) {
try {
Thread.sleep(500);
DefaultContext contextBean = bindCmp.getFirstContextBean();
contextBean.setData(CONTENT_KEY, "value");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("DCmp executed!");
}
}

View File

@ -0,0 +1,18 @@
package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import com.yomahub.liteflow.enums.NodeTypeEnum;
@LiteflowComponent("f")
@LiteflowCmpDefine(NodeTypeEnum.IF)
public class FCmp {
@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_IF, nodeType = NodeTypeEnum.IF)
public boolean processIf(NodeComponent bindCmp) throws Exception {
return true;
}
}

View File

@ -0,0 +1,18 @@
package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import com.yomahub.liteflow.enums.NodeTypeEnum;
@LiteflowComponent("s")
@LiteflowCmpDefine(NodeTypeEnum.SWITCH)
public class SCmp {
@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_SWITCH, nodeType = NodeTypeEnum.SWITCH)
public String processSwitch(NodeComponent bindCmp) throws Exception {
return "b";
}
}

View File

@ -0,0 +1,31 @@
package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import java.util.HashSet;
import java.util.Set;
@LiteflowComponent("w")
@LiteflowCmpDefine(NodeTypeEnum.WHILE)
public class WCmp {
private int count = 0;
// 执行过的 chain
Set<String> executedChain = new HashSet<>();
@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_WHILE, nodeType = NodeTypeEnum.WHILE)
public boolean processWhile(NodeComponent bindCmp) throws Exception {
// 判断是否切换了 chain
if (!executedChain.contains(bindCmp.getCurrChainId())) {
count = 0;
executedChain.add(bindCmp.getCurrChainId());
}
count++;
return count <= 2;
}
}

View File

@ -0,0 +1,23 @@
package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp;
import cn.hutool.core.collection.ListUtil;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import java.util.Iterator;
import java.util.List;
@LiteflowComponent("x")
@LiteflowCmpDefine(NodeTypeEnum.ITERATOR)
public class XCmp {
@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_ITERATOR, nodeType = NodeTypeEnum.ITERATOR)
public Iterator<?> processIterator(NodeComponent bindCmp) throws Exception {
List<String> list = ListUtil.toList("one", "two");
return list.iterator();
}
}

View File

@ -0,0 +1 @@
liteflow.rule-source=maxWaitMilliseconds/flow.el.xml

View File

@ -0,0 +1,110 @@
<?xml version="1.0" encoding="UTF-8"?>
<flow>
<!--
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>