enhancement #I821F1 增加测试案例,调整注释
This commit is contained in:
parent
7fdb5829f5
commit
ca9449f531
|
@ -216,53 +216,77 @@ public class FlowExecutor {
|
|||
}
|
||||
|
||||
/**
|
||||
* 检查 chain 的有效性,同时重新构建 FlowBus 的 chain,将调用的子 chain 连起来
|
||||
* 检查 chain 的有效性,同时重新构建 FlowBus 的 chain,将其子 chain 引用连起来
|
||||
* @throws CyclicDependencyException
|
||||
*/
|
||||
private void checkValidOfChain() {
|
||||
|
||||
// 存储已经构建完的有效的 chain 对应 Id
|
||||
Set<String> validChainIdSet = new HashSet<>();
|
||||
|
||||
// 遍历所有解析的 chain
|
||||
for (Chain rootChain : FlowBus.getChainMap().values()) {
|
||||
|
||||
// 不存在 validChainIdSet 中的 chain,说明还未检查
|
||||
if (!validChainIdSet.contains(rootChain.getChainId())) {
|
||||
|
||||
// 与 rootChain 相关联的 chain 的 ID
|
||||
Set<String> associatedChainIdSet = new HashSet<>();
|
||||
|
||||
// 检查 chain 的有效性,是否存在死循环情况
|
||||
checkValidOfChain(rootChain, associatedChainIdSet);
|
||||
|
||||
// 检查完当前 chain 后,能走到这里说明当前相关的 chain 是有效的
|
||||
validChainIdSet.addAll(associatedChainIdSet);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查 chain 的有效性
|
||||
* @param currentChain 当前遍历到的 chain 节点
|
||||
* @param associatedChainIdSet 与 rootChain 相关联的 chainId 集合
|
||||
* @throws CyclicDependencyException
|
||||
*/
|
||||
private void checkValidOfChain(Chain currentChain, Set<String> associatedChainIdSet) {
|
||||
// 判断 completedChainIdSet 中是否已经存在对应的 chain
|
||||
|
||||
// 判断 associatedChainIdSet 中是否已经存在对应的 chain
|
||||
if (associatedChainIdSet.add(currentChain.getChainId())) {
|
||||
|
||||
// Set 中不存在则说明可能是父 chain 或者子 chain 未引用自身,又或者子 chain 未引用其父 chain,继续判断其子 chain
|
||||
for (Condition condition : currentChain.getConditionList()) {
|
||||
|
||||
// 遍历所有 executable 列表
|
||||
for (Executable executable : condition.getExecutableList()) {
|
||||
|
||||
// 只需判断 chain,因为只有 chain 才会存在死循环依赖情况
|
||||
if (executable instanceof Chain) {
|
||||
|
||||
// 能执行到此处,必能从 FlowBus 中获取到对应的 chain,故无需做非空判断
|
||||
Chain childrenChain = FlowBus.getChainMap().get(executable.getId());
|
||||
|
||||
// 递归检查 chain 有效性
|
||||
checkValidOfChain(childrenChain, associatedChainIdSet);
|
||||
|
||||
// 重新构建 chain 的 condition 列表
|
||||
((Chain) executable).setConditionList(childrenChain.getConditionList());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
String errorMessage = StrUtil.format("There is a circular dependency in the chain[{}], please check carefully.", currentChain.getChainId());
|
||||
|
||||
LOG.error(errorMessage);
|
||||
|
||||
// chain 重复,说明子 chain 中引用了自身或其父 chain,存在死循环情况
|
||||
throw new CyclicDependencyException(StrUtil.format("There is a circular dependency in the chain[{}], please check carefully.", currentChain.getChainId()));
|
||||
throw new CyclicDependencyException(errorMessage);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 此方法就是从原有的配置源主动拉取新的进行刷新
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
|
||||
package com.yomahub.liteflow.test.subflow.endlessLopp;
|
||||
|
||||
import com.yomahub.liteflow.core.FlowExecutorHolder;
|
||||
import com.yomahub.liteflow.exception.CyclicDependencyException;
|
||||
import com.yomahub.liteflow.property.LiteflowConfig;
|
||||
import com.yomahub.liteflow.property.LiteflowConfigGetter;
|
||||
import com.yomahub.liteflow.test.BaseTest;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
||||
/**
|
||||
* 测试多文件情况下 chain 死循环逻辑
|
||||
*
|
||||
* @author luo yi
|
||||
* @since 2.11.1
|
||||
*/
|
||||
public class FlowInDifferentConfigTest extends BaseTest {
|
||||
|
||||
// 测试 chain 死循环
|
||||
@Test
|
||||
public void testChainEndlessLoop() {
|
||||
Assertions.assertThrows(CyclicDependencyException.class, () -> {
|
||||
LiteflowConfig config = LiteflowConfigGetter.get();
|
||||
config.setRuleSource("subflow/endlessLoop/flow-main.el.xml,subflow/endlessLoop/flow-sub1.el.xml");
|
||||
FlowExecutorHolder.loadInstance(config);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package com.yomahub.liteflow.test.subflow.endlessLopp;
|
||||
|
||||
import com.yomahub.liteflow.core.FlowExecutorHolder;
|
||||
import com.yomahub.liteflow.exception.CyclicDependencyException;
|
||||
import com.yomahub.liteflow.property.LiteflowConfig;
|
||||
import com.yomahub.liteflow.property.LiteflowConfigGetter;
|
||||
import com.yomahub.liteflow.test.BaseTest;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* 测试 json 文件情况下 chain 死循环逻辑
|
||||
*
|
||||
* @author luo yi
|
||||
* @since 2.11.1
|
||||
*/
|
||||
public class FlowJsonTest extends BaseTest {
|
||||
|
||||
// 测试 chain 死循环
|
||||
@Test
|
||||
public void testChainEndlessLoop() {
|
||||
Assertions.assertThrows(CyclicDependencyException.class, () -> {
|
||||
LiteflowConfig config = LiteflowConfigGetter.get();
|
||||
config.setRuleSource("subflow/endlessLoop/flow.el.json");
|
||||
FlowExecutorHolder.loadInstance(config);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package com.yomahub.liteflow.test.subflow.endlessLopp;
|
||||
|
||||
import com.yomahub.liteflow.core.FlowExecutorHolder;
|
||||
import com.yomahub.liteflow.exception.CyclicDependencyException;
|
||||
import com.yomahub.liteflow.property.LiteflowConfig;
|
||||
import com.yomahub.liteflow.property.LiteflowConfigGetter;
|
||||
import com.yomahub.liteflow.test.BaseTest;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* 测试 xml 文件情况下 chain 死循环逻辑
|
||||
*
|
||||
* @author luo yi
|
||||
* @since 2.11.1
|
||||
*/
|
||||
public class FlowXMLTest extends BaseTest {
|
||||
|
||||
// 测试 chain 死循环
|
||||
@Test
|
||||
public void testChainEndlessLoop() {
|
||||
Assertions.assertThrows(CyclicDependencyException.class, () -> {
|
||||
LiteflowConfig config = LiteflowConfigGetter.get();
|
||||
config.setRuleSource("subflow/endlessLoop/flow.el.xml");
|
||||
FlowExecutorHolder.loadInstance(config);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package com.yomahub.liteflow.test.subflow.endlessLopp;
|
||||
|
||||
import com.yomahub.liteflow.core.FlowExecutorHolder;
|
||||
import com.yomahub.liteflow.exception.CyclicDependencyException;
|
||||
import com.yomahub.liteflow.property.LiteflowConfig;
|
||||
import com.yomahub.liteflow.property.LiteflowConfigGetter;
|
||||
import com.yomahub.liteflow.test.BaseTest;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* 测试 yml 文件情况下 chain 死循环逻辑
|
||||
*
|
||||
* @author luo yi
|
||||
* @since 2.11.1
|
||||
*/
|
||||
public class FlowYMLTest extends BaseTest {
|
||||
|
||||
// 测试 chain 死循环
|
||||
@Test
|
||||
public void testChainEndlessLoop() {
|
||||
Assertions.assertThrows(CyclicDependencyException.class, () -> {
|
||||
LiteflowConfig config = LiteflowConfigGetter.get();
|
||||
config.setRuleSource("subflow/endlessLoop/flow.el.yml");
|
||||
FlowExecutorHolder.loadInstance(config);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<flow>
|
||||
<nodes>
|
||||
<node id="a" class="com.yomahub.liteflow.test.subflow.cmp1.ACmp"/>
|
||||
<node id="b" class="com.yomahub.liteflow.test.subflow.cmp1.BCmp"/>
|
||||
<node id="c" class="com.yomahub.liteflow.test.subflow.cmp1.CCmp"/>
|
||||
<node id="d" class="com.yomahub.liteflow.test.subflow.cmp1.DCmp"/>
|
||||
<node id="e" class="com.yomahub.liteflow.test.subflow.cmp1.ECmp"/>
|
||||
<node id="f" class="com.yomahub.liteflow.test.subflow.cmp2.FCmp"/>
|
||||
<node id="g" class="com.yomahub.liteflow.test.subflow.cmp2.GCmp"/>
|
||||
<node id="h" class="com.yomahub.liteflow.test.subflow.cmp2.HCmp"/>
|
||||
<node id="m" class="com.yomahub.liteflow.test.subflow.cmp2.MCmp"/>
|
||||
</nodes>
|
||||
<chain name="chain1">
|
||||
THEN(a, b, chain2);
|
||||
</chain>
|
||||
</flow>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<flow>
|
||||
<chain name="chain2">
|
||||
THEN(b, a, chain1);
|
||||
</chain>
|
||||
</flow>
|
|
@ -0,0 +1,58 @@
|
|||
{
|
||||
"flow": {
|
||||
"nodes": {
|
||||
"node": [
|
||||
{
|
||||
"id": "a",
|
||||
"class": "com.yomahub.liteflow.test.subflow.cmp1.ACmp"
|
||||
},
|
||||
{
|
||||
"id": "b",
|
||||
"class": "com.yomahub.liteflow.test.subflow.cmp1.BCmp"
|
||||
},
|
||||
{
|
||||
"id": "c",
|
||||
"class": "com.yomahub.liteflow.test.subflow.cmp1.CCmp"
|
||||
},
|
||||
{
|
||||
"id": "d",
|
||||
"class": "com.yomahub.liteflow.test.subflow.cmp1.DCmp"
|
||||
},
|
||||
{
|
||||
"id": "e",
|
||||
"class": "com.yomahub.liteflow.test.subflow.cmp1.ECmp"
|
||||
},
|
||||
{
|
||||
"id": "f",
|
||||
"class": "com.yomahub.liteflow.test.subflow.cmp2.FCmp"
|
||||
},
|
||||
{
|
||||
"id": "g",
|
||||
"class": "com.yomahub.liteflow.test.subflow.cmp2.GCmp"
|
||||
},
|
||||
{
|
||||
"id": "h",
|
||||
"class": "com.yomahub.liteflow.test.subflow.cmp2.HCmp"
|
||||
},
|
||||
{
|
||||
"id": "M",
|
||||
"class": "com.yomahub.liteflow.test.subflow.cmp2.MCmp"
|
||||
}
|
||||
]
|
||||
},
|
||||
"chain": [
|
||||
{
|
||||
"name": "chain7",
|
||||
"value": "THEN(a, chain8);"
|
||||
},
|
||||
{
|
||||
"name": "chain8",
|
||||
"value": "THEN(b, chain9);"
|
||||
},
|
||||
{
|
||||
"name": "chain9",
|
||||
"value": "WHEN(c, chain7);"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<flow>
|
||||
<nodes>
|
||||
<node id="a" class="com.yomahub.liteflow.test.subflow.cmp1.ACmp"/>
|
||||
<node id="b" class="com.yomahub.liteflow.test.subflow.cmp1.BCmp"/>
|
||||
<node id="c" class="com.yomahub.liteflow.test.subflow.cmp1.CCmp"/>
|
||||
<node id="d" class="com.yomahub.liteflow.test.subflow.cmp1.DCmp"/>
|
||||
<node id="e" class="com.yomahub.liteflow.test.subflow.cmp1.ECmp"/>
|
||||
<node id="f" class="com.yomahub.liteflow.test.subflow.cmp2.FCmp"/>
|
||||
<node id="g" class="com.yomahub.liteflow.test.subflow.cmp2.GCmp"/>
|
||||
<node id="h" class="com.yomahub.liteflow.test.subflow.cmp2.HCmp"/>
|
||||
<node id="m" class="com.yomahub.liteflow.test.subflow.cmp2.MCmp"/>
|
||||
</nodes>
|
||||
<chain name="chain1">
|
||||
THEN(a, chain2);
|
||||
</chain>
|
||||
|
||||
<chain name="chain2">
|
||||
THEN(b, chain3);
|
||||
</chain>
|
||||
|
||||
<chain name="chain3">
|
||||
THEN(c, chain1);
|
||||
</chain>
|
||||
</flow>
|
|
@ -0,0 +1,28 @@
|
|||
flow:
|
||||
nodes:
|
||||
node:
|
||||
- id: a
|
||||
class: com.yomahub.liteflow.test.subflow.cmp1.ACmp
|
||||
- id: b
|
||||
class: com.yomahub.liteflow.test.subflow.cmp1.BCmp
|
||||
- id: c
|
||||
class: com.yomahub.liteflow.test.subflow.cmp1.CCmp
|
||||
- id: d
|
||||
class: com.yomahub.liteflow.test.subflow.cmp1.DCmp
|
||||
- id: e
|
||||
class: com.yomahub.liteflow.test.subflow.cmp1.ECmp
|
||||
- id: f
|
||||
class: com.yomahub.liteflow.test.subflow.cmp2.FCmp
|
||||
- id: g
|
||||
class: com.yomahub.liteflow.test.subflow.cmp2.GCmp
|
||||
- id: h
|
||||
class: com.yomahub.liteflow.test.subflow.cmp2.HCmp
|
||||
- id: h
|
||||
class: com.yomahub.liteflow.test.subflow.cmp2.MCmp
|
||||
chain:
|
||||
- name: chain4
|
||||
value: "THEN(a, chain5);"
|
||||
- name: chain5
|
||||
value: "THEN(b, chain6);"
|
||||
- name: chain6
|
||||
value: "THEN(c, chain5);"
|
Loading…
Reference in New Issue