From 924768705c14eea00da680c8707d4420b20523bf Mon Sep 17 00:00:00 2001 From: Dale Lee <1658850308@qq.com> Date: Mon, 15 Jan 2024 21:46:36 +0800 Subject: [PATCH] =?UTF-8?q?feature=20#I8MW6Q=20=E5=AE=8C=E5=96=84=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yomahub/liteflow/flow/FlowBus.java | 30 ++++- .../script/jsr223/JSR223ScriptExecutor.java | 15 +-- .../graaljs/GraalJavaScriptExecutor.java | 6 - .../liteflow/script/java/JavaExecutor.java | 6 - .../LiteFlowAviatorScriptRemoveELTest.java | 114 ++++++++++++++++ .../resources/remove/application.properties | 1 + .../src/test/resources/remove/flow.xml | 30 +++++ .../remove/LiteFlowJsScriptRemoveELTest.java | 57 +++++++- .../LiteFlowGroovyScriptRemoveELTest.java | 114 ++++++++++++++++ .../resources/remove/application.properties | 1 + .../src/test/resources/remove/flow.xml | 30 +++++ .../LiteFlowJavaScriptRemoveELTest.java | 124 ++++++++++++++++++ .../resources/remove/application.properties | 1 + .../src/test/resources/remove/flow.xml | 50 +++++++ .../remove/LiteFlowJsScriptRemoveELTest.java | 28 +++- .../remove/LiteFlowLuaScriptRemoveELTest.java | 114 ++++++++++++++++ .../resources/remove/application.properties | 1 + .../src/test/resources/remove/flow.xml | 30 +++++ .../LiteFlowPythonScriptRemoveELTest.java | 114 ++++++++++++++++ .../resources/remove/application.properties | 1 + .../src/test/resources/remove/flow.xml | 30 +++++ .../LiteFlowQLExpressScriptRemoveELTest.java | 114 ++++++++++++++++ .../resources/remove/application.properties | 1 + .../src/test/resources/remove/flow.xml | 30 +++++ 24 files changed, 1003 insertions(+), 39 deletions(-) create mode 100644 liteflow-testcase-el/liteflow-testcase-el-script-aviator-springboot/src/test/java/com/yomahub/liteflow/test/script/aviator/remove/LiteFlowAviatorScriptRemoveELTest.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-script-aviator-springboot/src/test/resources/remove/application.properties create mode 100644 liteflow-testcase-el/liteflow-testcase-el-script-aviator-springboot/src/test/resources/remove/flow.xml create mode 100644 liteflow-testcase-el/liteflow-testcase-el-script-groovy-springboot/src/test/java/com/yomahub/liteflow/test/script/groovy/remove/LiteFlowGroovyScriptRemoveELTest.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-script-groovy-springboot/src/test/resources/remove/application.properties create mode 100644 liteflow-testcase-el/liteflow-testcase-el-script-groovy-springboot/src/test/resources/remove/flow.xml create mode 100644 liteflow-testcase-el/liteflow-testcase-el-script-java-springboot/src/test/java/com/yomahub/liteflow/test/script/java/remove/LiteFlowJavaScriptRemoveELTest.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-script-java-springboot/src/test/resources/remove/application.properties create mode 100644 liteflow-testcase-el/liteflow-testcase-el-script-java-springboot/src/test/resources/remove/flow.xml create mode 100644 liteflow-testcase-el/liteflow-testcase-el-script-lua-springboot/src/test/java/com/yomahub/liteflow/test/script/lua/remove/LiteFlowLuaScriptRemoveELTest.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-script-lua-springboot/src/test/resources/remove/application.properties create mode 100644 liteflow-testcase-el/liteflow-testcase-el-script-lua-springboot/src/test/resources/remove/flow.xml create mode 100644 liteflow-testcase-el/liteflow-testcase-el-script-python-springboot/src/test/java/com/yomahub/liteflow/test/script/python/remove/LiteFlowPythonScriptRemoveELTest.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-script-python-springboot/src/test/resources/remove/application.properties create mode 100644 liteflow-testcase-el/liteflow-testcase-el-script-python-springboot/src/test/resources/remove/flow.xml create mode 100644 liteflow-testcase-el/liteflow-testcase-el-script-qlexpress-springboot/src/test/java/com/yomahub/liteflow/test/script/qlexpress/remove/LiteFlowQLExpressScriptRemoveELTest.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-script-qlexpress-springboot/src/test/resources/remove/application.properties create mode 100644 liteflow-testcase-el/liteflow-testcase-el-script-qlexpress-springboot/src/test/resources/remove/flow.xml diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java index 9e8c9e8c7..abb9446a7 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java @@ -300,14 +300,19 @@ public class FlowBus { // 移除节点 public static boolean removeNode(String nodeId) { - if (containNode(nodeId)) { - nodeMap.remove(nodeId); - return true; - } else { - String errMsg = StrUtil.format("cannot find the node[{}]", nodeId); - LOG.error(errMsg); + Node node = getNode(nodeId); + if (node == null) { + // 节点不存在 return false; } + nodeMap.remove(nodeId); + // 如果是脚本节点,移除脚本 + if (node.getType().isScript()) { + ScriptExecutorFactory.loadInstance() + .getScriptExecutor(node.getLanguage()) + .unLoad(nodeId); + } + return true; } // 判断是否是降级组件,如果是则添加到 fallbackNodeMap @@ -322,6 +327,19 @@ public class FlowBus { fallbackNodeMap.put(nodeType, node); } + // 重新加载脚本 + public static void reloadScript(String nodeId, String script) { + Node node = getNode(nodeId); + if (node == null) { + return; + } + // 更新脚本 + node.setScript(script); + ScriptExecutorFactory.loadInstance() + .getScriptExecutor(node.getLanguage()) + .load(nodeId, script); + } + public static void clearStat(){ initStat.set(false); } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/script/jsr223/JSR223ScriptExecutor.java b/liteflow-core/src/main/java/com/yomahub/liteflow/script/jsr223/JSR223ScriptExecutor.java index 7141bffc6..61fece39f 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/script/jsr223/JSR223ScriptExecutor.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/script/jsr223/JSR223ScriptExecutor.java @@ -1,14 +1,19 @@ package com.yomahub.liteflow.script.jsr223; import cn.hutool.core.util.StrUtil; -import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.log.LFLog; import com.yomahub.liteflow.log.LFLoggerManager; import com.yomahub.liteflow.script.ScriptExecuteWrap; import com.yomahub.liteflow.script.ScriptExecutor; import com.yomahub.liteflow.script.exception.ScriptLoadException; import com.yomahub.liteflow.util.CopyOnWriteHashMap; -import javax.script.*; + +import javax.script.Bindings; +import javax.script.Compilable; +import javax.script.CompiledScript; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import javax.script.SimpleBindings; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -43,10 +48,6 @@ public abstract class JSR223ScriptExecutor extends ScriptExecutor { try { CompiledScript compiledScript = ((Compilable) scriptEngine).compile(convertScript(script)); compiledScriptMap.put(nodeId, compiledScript); - // 更新 node - if (FlowBus.containNode(nodeId)) { - FlowBus.getNode(nodeId).setScript(script); - } } catch (Exception e) { String errorMsg = StrUtil.format("script loading error for node[{}], error msg:{}", nodeId, e.getMessage()); @@ -57,8 +58,6 @@ public abstract class JSR223ScriptExecutor extends ScriptExecutor { @Override public void unLoad(String nodeId) { compiledScriptMap.remove(nodeId); - // 移除节点 - FlowBus.removeNode(nodeId); } @Override diff --git a/liteflow-script-plugin/liteflow-script-graaljs/src/main/java/com/yomahub/liteflow/script/graaljs/GraalJavaScriptExecutor.java b/liteflow-script-plugin/liteflow-script-graaljs/src/main/java/com/yomahub/liteflow/script/graaljs/GraalJavaScriptExecutor.java index 1d8d7b1d5..24260e630 100644 --- a/liteflow-script-plugin/liteflow-script-graaljs/src/main/java/com/yomahub/liteflow/script/graaljs/GraalJavaScriptExecutor.java +++ b/liteflow-script-plugin/liteflow-script-graaljs/src/main/java/com/yomahub/liteflow/script/graaljs/GraalJavaScriptExecutor.java @@ -40,10 +40,6 @@ public class GraalJavaScriptExecutor extends ScriptExecutor { try { String wrapScript = StrUtil.format("function process(){{}} process();", script); scriptMap.put(nodeId, Source.create("js", wrapScript)); - // 更新 node - if (FlowBus.containNode(nodeId)) { - FlowBus.getNode(nodeId).setScript(script); - } } catch (Exception e) { String errorMsg = StrUtil.format("script loading error for node[{}], error msg:{}", nodeId, e.getMessage()); @@ -54,8 +50,6 @@ public class GraalJavaScriptExecutor extends ScriptExecutor { @Override public void unLoad(String nodeId) { scriptMap.remove(nodeId); - // 移除节点 - FlowBus.removeNode(nodeId); } @Override diff --git a/liteflow-script-plugin/liteflow-script-java/src/main/java/com/yomahub/liteflow/script/java/JavaExecutor.java b/liteflow-script-plugin/liteflow-script-java/src/main/java/com/yomahub/liteflow/script/java/JavaExecutor.java index 7154a2fe6..e7861d38a 100644 --- a/liteflow-script-plugin/liteflow-script-java/src/main/java/com/yomahub/liteflow/script/java/JavaExecutor.java +++ b/liteflow-script-plugin/liteflow-script-java/src/main/java/com/yomahub/liteflow/script/java/JavaExecutor.java @@ -29,10 +29,6 @@ public class JavaExecutor extends ScriptExecutor { se.setParameters(new String[] {"_meta"}, new Class[] {ScriptExecuteWrap.class}); se.cook(convertScript(script)); compiledScriptMap.put(nodeId, se); - // 更新 node - if (FlowBus.containNode(nodeId)) { - FlowBus.getNode(nodeId).setScript(script); - } }catch (Exception e){ String errorMsg = StrUtil.format("script loading error for node[{}],error msg:{}", nodeId, e.getMessage()); throw new ScriptLoadException(errorMsg); @@ -43,8 +39,6 @@ public class JavaExecutor extends ScriptExecutor { @Override public void unLoad(String nodeId) { compiledScriptMap.remove(nodeId); - // 移除节点 - FlowBus.removeNode(nodeId); } @Override diff --git a/liteflow-testcase-el/liteflow-testcase-el-script-aviator-springboot/src/test/java/com/yomahub/liteflow/test/script/aviator/remove/LiteFlowAviatorScriptRemoveELTest.java b/liteflow-testcase-el/liteflow-testcase-el-script-aviator-springboot/src/test/java/com/yomahub/liteflow/test/script/aviator/remove/LiteFlowAviatorScriptRemoveELTest.java new file mode 100644 index 000000000..738bd09e5 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-script-aviator-springboot/src/test/java/com/yomahub/liteflow/test/script/aviator/remove/LiteFlowAviatorScriptRemoveELTest.java @@ -0,0 +1,114 @@ +package com.yomahub.liteflow.test.script.aviator.remove; + +import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; +import com.yomahub.liteflow.core.FlowExecutor; +import com.yomahub.liteflow.enums.ScriptTypeEnum; +import com.yomahub.liteflow.exception.ELParseException; +import com.yomahub.liteflow.flow.FlowBus; +import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.script.ScriptExecutor; +import com.yomahub.liteflow.script.ScriptExecutorFactory; +import com.yomahub.liteflow.script.exception.ScriptLoadException; +import com.yomahub.liteflow.slot.DefaultContext; +import com.yomahub.liteflow.test.BaseTest; +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.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 测试脚本的卸载和重载功能 + * + * @author DaleLee + */ +@ExtendWith(SpringExtension.class) +@TestPropertySource(value = "classpath:/remove/application.properties") +@SpringBootTest(classes = LiteFlowAviatorScriptRemoveELTest.class) +@EnableAutoConfiguration +public class LiteFlowAviatorScriptRemoveELTest extends BaseTest { + + @Resource + private FlowExecutor flowExecutor; + + private ScriptExecutor scriptExecutor = ScriptExecutorFactory.loadInstance() + .getScriptExecutor(ScriptTypeEnum.AVIATOR.getDisplayName()); + + // 仅卸载脚本 + @Test + public void testUnload() { + flowExecutor.reloadRule(); + + // 获取节点id + List nodeIds = scriptExecutor.getNodeIds(); + Assertions.assertEquals(2, nodeIds.size()); + Assertions.assertTrue(nodeIds.contains("s1")); + Assertions.assertTrue(nodeIds.contains("s2")); + + // 保证脚本可以正常运行 + LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); + Assertions.assertTrue(response.isSuccess()); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertEquals(Long.valueOf(6), context.getData("s1")); + + // 卸载脚本 + scriptExecutor.unLoad("s1"); + response = flowExecutor.execute2Resp("chain1", "arg"); + Assertions.assertFalse(response.isSuccess()); + Assertions.assertEquals(ScriptLoadException.class, response.getCause().getClass()); + Assertions.assertEquals("script for node[s1] is not loaded", response.getMessage()); + + // 脚本已卸载 + Assertions.assertFalse(scriptExecutor.getNodeIds().contains("s1")); + } + + // 卸载节点和脚本 + @Test + public void testRemove() { + flowExecutor.reloadRule(); + + // 保证脚本可以正常运行 + LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg"); + Assertions.assertTrue(response.isSuccess()); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertEquals(Long.valueOf(5), context.getData("s2")); + + // 卸载节点 + FlowBus.removeNode("s2"); + + // 旧 chain 报脚本加载错误 + response = flowExecutor.execute2Resp("chain2", "arg"); + Assertions.assertEquals(ScriptLoadException.class, response.getCause().getClass()); + + // 新 chian 会找不到节点 + Assertions.assertThrows(ELParseException.class, + () -> LiteFlowChainELBuilder.createChain() + .setChainId("chain3") + .setEL("THEN(s2)") + .build()); + + // 节点已卸载 + Assertions.assertFalse(FlowBus.containNode("s2")); + // 脚本已卸载 + Assertions.assertFalse(scriptExecutor.getNodeIds().contains("s2")); + } + + // 重载脚本 + @Test + public void testReloadScript() { + flowExecutor.reloadRule(); + String script = "setData(defaultContext,\"s1\",\"abc\");"; + FlowBus.reloadScript("s1", script); + LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); + DefaultContext context = response.getFirstContextBean(); + // 执行结果变更 + Assertions.assertEquals("abc", context.getData("s1")); + // 脚本变更 + Assertions.assertEquals(FlowBus.getNode("s1").getScript(), script); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-script-aviator-springboot/src/test/resources/remove/application.properties b/liteflow-testcase-el/liteflow-testcase-el-script-aviator-springboot/src/test/resources/remove/application.properties new file mode 100644 index 000000000..21b596255 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-script-aviator-springboot/src/test/resources/remove/application.properties @@ -0,0 +1 @@ +liteflow.rule-source=remove/flow.xml \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-script-aviator-springboot/src/test/resources/remove/flow.xml b/liteflow-testcase-el/liteflow-testcase-el-script-aviator-springboot/src/test/resources/remove/flow.xml new file mode 100644 index 000000000..a9c631831 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-script-aviator-springboot/src/test/resources/remove/flow.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + THEN(s1); + + + + THEN(s2); + + \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-script-graaljs-springboot/src/test/java/com/yomahub/liteflow/test/script/graaljs/remove/LiteFlowJsScriptRemoveELTest.java b/liteflow-testcase-el/liteflow-testcase-el-script-graaljs-springboot/src/test/java/com/yomahub/liteflow/test/script/graaljs/remove/LiteFlowJsScriptRemoveELTest.java index 6e0491c3c..86db95027 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-script-graaljs-springboot/src/test/java/com/yomahub/liteflow/test/script/graaljs/remove/LiteFlowJsScriptRemoveELTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-script-graaljs-springboot/src/test/java/com/yomahub/liteflow/test/script/graaljs/remove/LiteFlowJsScriptRemoveELTest.java @@ -23,7 +23,7 @@ import javax.annotation.Resource; import java.util.List; /** - * 测试脚本的卸载功能 + * 测试脚本的卸载和重载功能 * * @author DaleLee */ @@ -36,14 +36,17 @@ public class LiteFlowJsScriptRemoveELTest extends BaseTest { @Resource private FlowExecutor flowExecutor; + private ScriptExecutor scriptExecutor = ScriptExecutorFactory.loadInstance() + .getScriptExecutor(ScriptTypeEnum.JS.getDisplayName()); + + // 仅卸载脚本 @Test public void testUnload() { - ScriptExecutor scriptExecutor = ScriptExecutorFactory.loadInstance() - .getScriptExecutor(ScriptTypeEnum.JS.getDisplayName()); + flowExecutor.reloadRule(); // 获取节点id List nodeIds = scriptExecutor.getNodeIds(); - Assertions.assertEquals(nodeIds.size(), 2); + Assertions.assertEquals(2, nodeIds.size()); Assertions.assertTrue(nodeIds.contains("s1")); Assertions.assertTrue(nodeIds.contains("s2")); @@ -62,8 +65,50 @@ public class LiteFlowJsScriptRemoveELTest extends BaseTest { // 脚本已卸载 Assertions.assertFalse(scriptExecutor.getNodeIds().contains("s1")); + } + + // 卸载节点和脚本 + @Test + public void testRemove() { + flowExecutor.reloadRule(); + + // 保证脚本可以正常运行 + LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg"); + Assertions.assertTrue(response.isSuccess()); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertEquals(Integer.valueOf(5), context.getData("s2")); + + // 卸载节点 + FlowBus.removeNode("s2"); + + // 旧 chain 报脚本加载错误 + response = flowExecutor.execute2Resp("chain2", "arg"); + Assertions.assertEquals(ScriptLoadException.class, response.getCause().getClass()); + + // 新 chian 会找不到节点 + Assertions.assertThrows(ELParseException.class, + () -> LiteFlowChainELBuilder.createChain() + .setChainId("chain3") + .setEL("THEN(s2)") + .build()); + // 节点已卸载 - Assertions.assertFalse(FlowBus.containNode("s1")); - Assertions.assertFalse(FlowBus.removeNode("s1")); + Assertions.assertFalse(FlowBus.containNode("s2")); + // 脚本已卸载 + Assertions.assertFalse(scriptExecutor.getNodeIds().contains("s2")); + } + + // 重载脚本 + @Test + public void testReloadScript() { + flowExecutor.reloadRule(); + String script = "defaultContext.setData(\"s1\",\"abc\");"; + FlowBus.reloadScript("s1", script); + LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); + DefaultContext context = response.getFirstContextBean(); + // 执行结果变更 + Assertions.assertEquals("abc", context.getData("s1")); + // 脚本变更 + Assertions.assertEquals(FlowBus.getNode("s1").getScript(), script); } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-script-groovy-springboot/src/test/java/com/yomahub/liteflow/test/script/groovy/remove/LiteFlowGroovyScriptRemoveELTest.java b/liteflow-testcase-el/liteflow-testcase-el-script-groovy-springboot/src/test/java/com/yomahub/liteflow/test/script/groovy/remove/LiteFlowGroovyScriptRemoveELTest.java new file mode 100644 index 000000000..e1c0e6ad6 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-script-groovy-springboot/src/test/java/com/yomahub/liteflow/test/script/groovy/remove/LiteFlowGroovyScriptRemoveELTest.java @@ -0,0 +1,114 @@ +package com.yomahub.liteflow.test.script.groovy.remove; + +import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; +import com.yomahub.liteflow.core.FlowExecutor; +import com.yomahub.liteflow.enums.ScriptTypeEnum; +import com.yomahub.liteflow.exception.ELParseException; +import com.yomahub.liteflow.flow.FlowBus; +import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.script.ScriptExecutor; +import com.yomahub.liteflow.script.ScriptExecutorFactory; +import com.yomahub.liteflow.script.exception.ScriptLoadException; +import com.yomahub.liteflow.slot.DefaultContext; +import com.yomahub.liteflow.test.BaseTest; +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.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 测试脚本的卸载和重载功能 + * + * @author DaleLee + */ +@ExtendWith(SpringExtension.class) +@TestPropertySource(value = "classpath:/remove/application.properties") +@SpringBootTest(classes = LiteFlowGroovyScriptRemoveELTest.class) +@EnableAutoConfiguration +public class LiteFlowGroovyScriptRemoveELTest extends BaseTest { + + @Resource + private FlowExecutor flowExecutor; + + private ScriptExecutor scriptExecutor = ScriptExecutorFactory.loadInstance() + .getScriptExecutor(ScriptTypeEnum.GROOVY.getDisplayName()); + + // 仅卸载脚本 + @Test + public void testUnload() { + flowExecutor.reloadRule(); + + // 获取节点id + List nodeIds = scriptExecutor.getNodeIds(); + Assertions.assertEquals(2, nodeIds.size()); + Assertions.assertTrue(nodeIds.contains("s1")); + Assertions.assertTrue(nodeIds.contains("s2")); + + // 保证脚本可以正常运行 + LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); + Assertions.assertTrue(response.isSuccess()); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertEquals(Integer.valueOf(6), context.getData("s1")); + + // 卸载脚本 + scriptExecutor.unLoad("s1"); + response = flowExecutor.execute2Resp("chain1", "arg"); + Assertions.assertFalse(response.isSuccess()); + Assertions.assertEquals(ScriptLoadException.class, response.getCause().getClass()); + Assertions.assertEquals("script for node[s1] is not loaded", response.getMessage()); + + // 脚本已卸载 + Assertions.assertFalse(scriptExecutor.getNodeIds().contains("s1")); + } + + // 卸载节点和脚本 + @Test + public void testRemove() { + flowExecutor.reloadRule(); + + // 保证脚本可以正常运行 + LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg"); + Assertions.assertTrue(response.isSuccess()); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertEquals(Integer.valueOf(5), context.getData("s2")); + + // 卸载节点 + FlowBus.removeNode("s2"); + + // 旧 chain 报脚本加载错误 + response = flowExecutor.execute2Resp("chain2", "arg"); + Assertions.assertEquals(ScriptLoadException.class, response.getCause().getClass()); + + // 新 chian 会找不到节点 + Assertions.assertThrows(ELParseException.class, + () -> LiteFlowChainELBuilder.createChain() + .setChainId("chain3") + .setEL("THEN(s2)") + .build()); + + // 节点已卸载 + Assertions.assertFalse(FlowBus.containNode("s2")); + // 脚本已卸载 + Assertions.assertFalse(scriptExecutor.getNodeIds().contains("s2")); + } + + // 重载脚本 + @Test + public void testReloadScript() { + flowExecutor.reloadRule(); + String script = "defaultContext.setData(\"s1\",\"abc\");"; + FlowBus.reloadScript("s1", script); + LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); + DefaultContext context = response.getFirstContextBean(); + // 执行结果变更 + Assertions.assertEquals("abc", context.getData("s1")); + // 脚本变更 + Assertions.assertEquals(FlowBus.getNode("s1").getScript(), script); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-script-groovy-springboot/src/test/resources/remove/application.properties b/liteflow-testcase-el/liteflow-testcase-el-script-groovy-springboot/src/test/resources/remove/application.properties new file mode 100644 index 000000000..21b596255 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-script-groovy-springboot/src/test/resources/remove/application.properties @@ -0,0 +1 @@ +liteflow.rule-source=remove/flow.xml \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-script-groovy-springboot/src/test/resources/remove/flow.xml b/liteflow-testcase-el/liteflow-testcase-el-script-groovy-springboot/src/test/resources/remove/flow.xml new file mode 100644 index 000000000..9dbcefb10 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-script-groovy-springboot/src/test/resources/remove/flow.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + THEN(s1); + + + + THEN(s2); + + \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-script-java-springboot/src/test/java/com/yomahub/liteflow/test/script/java/remove/LiteFlowJavaScriptRemoveELTest.java b/liteflow-testcase-el/liteflow-testcase-el-script-java-springboot/src/test/java/com/yomahub/liteflow/test/script/java/remove/LiteFlowJavaScriptRemoveELTest.java new file mode 100644 index 000000000..205ba5a36 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-script-java-springboot/src/test/java/com/yomahub/liteflow/test/script/java/remove/LiteFlowJavaScriptRemoveELTest.java @@ -0,0 +1,124 @@ +package com.yomahub.liteflow.test.script.java.remove; + +import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; +import com.yomahub.liteflow.core.FlowExecutor; +import com.yomahub.liteflow.enums.ScriptTypeEnum; +import com.yomahub.liteflow.exception.ELParseException; +import com.yomahub.liteflow.flow.FlowBus; +import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.script.ScriptExecutor; +import com.yomahub.liteflow.script.ScriptExecutorFactory; +import com.yomahub.liteflow.script.exception.ScriptLoadException; +import com.yomahub.liteflow.slot.DefaultContext; +import com.yomahub.liteflow.test.BaseTest; +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.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 测试脚本的卸载和重载功能 + * + * @author DaleLee + */ +@ExtendWith(SpringExtension.class) +@TestPropertySource(value = "classpath:/remove/application.properties") +@SpringBootTest(classes = LiteFlowJavaScriptRemoveELTest.class) +@EnableAutoConfiguration +public class LiteFlowJavaScriptRemoveELTest extends BaseTest { + + @Resource + private FlowExecutor flowExecutor; + + private ScriptExecutor scriptExecutor = ScriptExecutorFactory.loadInstance() + .getScriptExecutor(ScriptTypeEnum.JAVA.getDisplayName()); + + // 仅卸载脚本 + @Test + public void testUnload() { + flowExecutor.reloadRule(); + + // 获取节点id + List nodeIds = scriptExecutor.getNodeIds(); + Assertions.assertEquals(2, nodeIds.size()); + Assertions.assertTrue(nodeIds.contains("s1")); + Assertions.assertTrue(nodeIds.contains("s2")); + + // 保证脚本可以正常运行 + LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); + Assertions.assertTrue(response.isSuccess()); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertEquals(Integer.valueOf(6), context.getData("s1")); + + // 卸载脚本 + scriptExecutor.unLoad("s1"); + response = flowExecutor.execute2Resp("chain1", "arg"); + Assertions.assertFalse(response.isSuccess()); + Assertions.assertEquals(ScriptLoadException.class, response.getCause().getClass()); + Assertions.assertEquals("script for node[s1] is not loaded", response.getMessage()); + + // 脚本已卸载 + Assertions.assertFalse(scriptExecutor.getNodeIds().contains("s1")); + } + + // 卸载节点和脚本 + @Test + public void testRemove() { + flowExecutor.reloadRule(); + + // 保证脚本可以正常运行 + LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg"); + Assertions.assertTrue(response.isSuccess()); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertEquals(Integer.valueOf(5), context.getData("s2")); + + // 卸载节点 + FlowBus.removeNode("s2"); + + // 旧 chain 报脚本加载错误 + response = flowExecutor.execute2Resp("chain2", "arg"); + Assertions.assertEquals(ScriptLoadException.class, response.getCause().getClass()); + + // 新 chian 会找不到节点 + Assertions.assertThrows(ELParseException.class, + () -> LiteFlowChainELBuilder.createChain() + .setChainId("chain3") + .setEL("THEN(s2)") + .build()); + + // 节点已卸载 + Assertions.assertFalse(FlowBus.containNode("s2")); + // 脚本已卸载 + Assertions.assertFalse(scriptExecutor.getNodeIds().contains("s2")); + } + + // 重载脚本 + @Test + public void testReloadScript() { + flowExecutor.reloadRule(); + String script = " import com.yomahub.liteflow.slot.DefaultContext;\n" + + " import com.yomahub.liteflow.script.body.JaninoCommonScriptBody;\n" + + " import com.yomahub.liteflow.script.ScriptExecuteWrap;\n" + + "\n" + + " public class Demo implements JaninoCommonScriptBody {\n" + + " public Void body(ScriptExecuteWrap wrap) {\n" + + " DefaultContext ctx = (DefaultContext) wrap.getCmp().getFirstContextBean();\n" + + " ctx.setData(\"s1\", \"abc\");\n" + + " return null;\n" + + " }\n" + + " }"; + FlowBus.reloadScript("s1", script); + LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); + DefaultContext context = response.getFirstContextBean(); + // 执行结果变更 + Assertions.assertEquals("abc", context.getData("s1")); + // 脚本变更 + Assertions.assertEquals(FlowBus.getNode("s1").getScript(), script); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-script-java-springboot/src/test/resources/remove/application.properties b/liteflow-testcase-el/liteflow-testcase-el-script-java-springboot/src/test/resources/remove/application.properties new file mode 100644 index 000000000..21b596255 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-script-java-springboot/src/test/resources/remove/application.properties @@ -0,0 +1 @@ +liteflow.rule-source=remove/flow.xml \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-script-java-springboot/src/test/resources/remove/flow.xml b/liteflow-testcase-el/liteflow-testcase-el-script-java-springboot/src/test/resources/remove/flow.xml new file mode 100644 index 000000000..dded8d6f5 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-script-java-springboot/src/test/resources/remove/flow.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + THEN(s1); + + + + THEN(s2); + + \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-script-javascript-springboot/src/test/java/com/yomahub/liteflow/test/script/javascript/remove/LiteFlowJsScriptRemoveELTest.java b/liteflow-testcase-el/liteflow-testcase-el-script-javascript-springboot/src/test/java/com/yomahub/liteflow/test/script/javascript/remove/LiteFlowJsScriptRemoveELTest.java index ce0f25210..a104fd333 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-script-javascript-springboot/src/test/java/com/yomahub/liteflow/test/script/javascript/remove/LiteFlowJsScriptRemoveELTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-script-javascript-springboot/src/test/java/com/yomahub/liteflow/test/script/javascript/remove/LiteFlowJsScriptRemoveELTest.java @@ -16,7 +16,6 @@ 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; @@ -47,7 +46,7 @@ public class LiteFlowJsScriptRemoveELTest extends BaseTest { // 获取节点id List nodeIds = scriptExecutor.getNodeIds(); - Assertions.assertEquals(nodeIds.size(), 2); + Assertions.assertEquals(2, nodeIds.size()); Assertions.assertTrue(nodeIds.contains("s1")); Assertions.assertTrue(nodeIds.contains("s2")); @@ -55,7 +54,7 @@ public class LiteFlowJsScriptRemoveELTest extends BaseTest { LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); Assertions.assertTrue(response.isSuccess()); DefaultContext context = response.getFirstContextBean(); - Assertions.assertEquals(Integer.valueOf(6), context.getData("s1")); + Assertions.assertEquals(Double.valueOf(6), context.getData("s1")); // 卸载脚本 scriptExecutor.unLoad("s1"); @@ -77,7 +76,7 @@ public class LiteFlowJsScriptRemoveELTest extends BaseTest { LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg"); Assertions.assertTrue(response.isSuccess()); DefaultContext context = response.getFirstContextBean(); - Assertions.assertEquals(Integer.valueOf(5), context.getData("s2")); + Assertions.assertEquals(Double.valueOf(5), context.getData("s2")); // 卸载节点 FlowBus.removeNode("s2"); @@ -88,13 +87,28 @@ public class LiteFlowJsScriptRemoveELTest extends BaseTest { // 新 chian 会找不到节点 Assertions.assertThrows(ELParseException.class, - () -> LiteFlowChainELBuilder.createChain().setChainId("chain3").setEL( - "THEN(s2)" - ).build()); + () -> LiteFlowChainELBuilder.createChain() + .setChainId("chain3") + .setEL("THEN(s2)") + .build()); // 节点已卸载 Assertions.assertFalse(FlowBus.containNode("s2")); // 脚本已卸载 Assertions.assertFalse(scriptExecutor.getNodeIds().contains("s2")); } + + // 重载脚本 + @Test + public void testReloadScript() { + flowExecutor.reloadRule(); + String script = "defaultContext.setData(\"s1\",\"abc\");"; + FlowBus.reloadScript("s1", script); + LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); + DefaultContext context = response.getFirstContextBean(); + // 执行结果变更 + Assertions.assertEquals("abc", context.getData("s1")); + // 脚本变更 + Assertions.assertEquals(FlowBus.getNode("s1").getScript(), script); + } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-script-lua-springboot/src/test/java/com/yomahub/liteflow/test/script/lua/remove/LiteFlowLuaScriptRemoveELTest.java b/liteflow-testcase-el/liteflow-testcase-el-script-lua-springboot/src/test/java/com/yomahub/liteflow/test/script/lua/remove/LiteFlowLuaScriptRemoveELTest.java new file mode 100644 index 000000000..951d0a94a --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-script-lua-springboot/src/test/java/com/yomahub/liteflow/test/script/lua/remove/LiteFlowLuaScriptRemoveELTest.java @@ -0,0 +1,114 @@ +package com.yomahub.liteflow.test.script.lua.remove; + +import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; +import com.yomahub.liteflow.core.FlowExecutor; +import com.yomahub.liteflow.enums.ScriptTypeEnum; +import com.yomahub.liteflow.exception.ELParseException; +import com.yomahub.liteflow.flow.FlowBus; +import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.script.ScriptExecutor; +import com.yomahub.liteflow.script.ScriptExecutorFactory; +import com.yomahub.liteflow.script.exception.ScriptLoadException; +import com.yomahub.liteflow.slot.DefaultContext; +import com.yomahub.liteflow.test.BaseTest; +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.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 测试脚本的卸载和重载功能 + * + * @author DaleLee + */ +@ExtendWith(SpringExtension.class) +@TestPropertySource(value = "classpath:/remove/application.properties") +@SpringBootTest(classes = LiteFlowLuaScriptRemoveELTest.class) +@EnableAutoConfiguration +public class LiteFlowLuaScriptRemoveELTest extends BaseTest { + + @Resource + private FlowExecutor flowExecutor; + + private ScriptExecutor scriptExecutor = ScriptExecutorFactory.loadInstance() + .getScriptExecutor(ScriptTypeEnum.LUA.getDisplayName()); + + // 仅卸载脚本 + @Test + public void testUnload() { + flowExecutor.reloadRule(); + + // 获取节点id + List nodeIds = scriptExecutor.getNodeIds(); + Assertions.assertEquals(2, nodeIds.size()); + Assertions.assertTrue(nodeIds.contains("s1")); + Assertions.assertTrue(nodeIds.contains("s2")); + + // 保证脚本可以正常运行 + LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); + Assertions.assertTrue(response.isSuccess()); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertEquals(Integer.valueOf(6), context.getData("s1")); + + // 卸载脚本 + scriptExecutor.unLoad("s1"); + response = flowExecutor.execute2Resp("chain1", "arg"); + Assertions.assertFalse(response.isSuccess()); + Assertions.assertEquals(ScriptLoadException.class, response.getCause().getClass()); + Assertions.assertEquals("script for node[s1] is not loaded", response.getMessage()); + + // 脚本已卸载 + Assertions.assertFalse(scriptExecutor.getNodeIds().contains("s1")); + } + + // 卸载节点和脚本 + @Test + public void testRemove() { + flowExecutor.reloadRule(); + + // 保证脚本可以正常运行 + LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg"); + Assertions.assertTrue(response.isSuccess()); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertEquals(Integer.valueOf(5), context.getData("s2")); + + // 卸载节点 + FlowBus.removeNode("s2"); + + // 旧 chain 报脚本加载错误 + response = flowExecutor.execute2Resp("chain2", "arg"); + Assertions.assertEquals(ScriptLoadException.class, response.getCause().getClass()); + + // 新 chian 会找不到节点 + Assertions.assertThrows(ELParseException.class, + () -> LiteFlowChainELBuilder.createChain() + .setChainId("chain3") + .setEL("THEN(s2)") + .build()); + + // 节点已卸载 + Assertions.assertFalse(FlowBus.containNode("s2")); + // 脚本已卸载 + Assertions.assertFalse(scriptExecutor.getNodeIds().contains("s2")); + } + + // 重载脚本 + @Test + public void testReloadScript() { + flowExecutor.reloadRule(); + String script = "defaultContext:setData(\"s1\",\"abc\");"; + FlowBus.reloadScript("s1", script); + LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); + DefaultContext context = response.getFirstContextBean(); + // 执行结果变更 + Assertions.assertEquals("abc", context.getData("s1")); + // 脚本变更 + Assertions.assertEquals(FlowBus.getNode("s1").getScript(), script); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-script-lua-springboot/src/test/resources/remove/application.properties b/liteflow-testcase-el/liteflow-testcase-el-script-lua-springboot/src/test/resources/remove/application.properties new file mode 100644 index 000000000..21b596255 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-script-lua-springboot/src/test/resources/remove/application.properties @@ -0,0 +1 @@ +liteflow.rule-source=remove/flow.xml \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-script-lua-springboot/src/test/resources/remove/flow.xml b/liteflow-testcase-el/liteflow-testcase-el-script-lua-springboot/src/test/resources/remove/flow.xml new file mode 100644 index 000000000..80888321f --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-script-lua-springboot/src/test/resources/remove/flow.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + THEN(s1); + + + + THEN(s2); + + \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-script-python-springboot/src/test/java/com/yomahub/liteflow/test/script/python/remove/LiteFlowPythonScriptRemoveELTest.java b/liteflow-testcase-el/liteflow-testcase-el-script-python-springboot/src/test/java/com/yomahub/liteflow/test/script/python/remove/LiteFlowPythonScriptRemoveELTest.java new file mode 100644 index 000000000..fd06b7eaa --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-script-python-springboot/src/test/java/com/yomahub/liteflow/test/script/python/remove/LiteFlowPythonScriptRemoveELTest.java @@ -0,0 +1,114 @@ +package com.yomahub.liteflow.test.script.python.remove; + +import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; +import com.yomahub.liteflow.core.FlowExecutor; +import com.yomahub.liteflow.enums.ScriptTypeEnum; +import com.yomahub.liteflow.exception.ELParseException; +import com.yomahub.liteflow.flow.FlowBus; +import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.script.ScriptExecutor; +import com.yomahub.liteflow.script.ScriptExecutorFactory; +import com.yomahub.liteflow.script.exception.ScriptLoadException; +import com.yomahub.liteflow.slot.DefaultContext; +import com.yomahub.liteflow.test.BaseTest; +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.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 测试脚本的卸载和重载功能 + * + * @author DaleLee + */ +@ExtendWith(SpringExtension.class) +@TestPropertySource(value = "classpath:/remove/application.properties") +@SpringBootTest(classes = LiteFlowPythonScriptRemoveELTest.class) +@EnableAutoConfiguration +public class LiteFlowPythonScriptRemoveELTest extends BaseTest { + + @Resource + private FlowExecutor flowExecutor; + + private ScriptExecutor scriptExecutor = ScriptExecutorFactory.loadInstance() + .getScriptExecutor(ScriptTypeEnum.PYTHON.getDisplayName()); + + // 仅卸载脚本 + @Test + public void testUnload() { + flowExecutor.reloadRule(); + + // 获取节点id + List nodeIds = scriptExecutor.getNodeIds(); + Assertions.assertEquals(2, nodeIds.size()); + Assertions.assertTrue(nodeIds.contains("s1")); + Assertions.assertTrue(nodeIds.contains("s2")); + + // 保证脚本可以正常运行 + LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); + Assertions.assertTrue(response.isSuccess()); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertEquals(Integer.valueOf(6), context.getData("s1")); + + // 卸载脚本 + scriptExecutor.unLoad("s1"); + response = flowExecutor.execute2Resp("chain1", "arg"); + Assertions.assertFalse(response.isSuccess()); + Assertions.assertEquals(ScriptLoadException.class, response.getCause().getClass()); + Assertions.assertEquals("script for node[s1] is not loaded", response.getMessage()); + + // 脚本已卸载 + Assertions.assertFalse(scriptExecutor.getNodeIds().contains("s1")); + } + + // 卸载节点和脚本 + @Test + public void testRemove() { + flowExecutor.reloadRule(); + + // 保证脚本可以正常运行 + LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg"); + Assertions.assertTrue(response.isSuccess()); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertEquals(Integer.valueOf(5), context.getData("s2")); + + // 卸载节点 + FlowBus.removeNode("s2"); + + // 旧 chain 报脚本加载错误 + response = flowExecutor.execute2Resp("chain2", "arg"); + Assertions.assertEquals(ScriptLoadException.class, response.getCause().getClass()); + + // 新 chian 会找不到节点 + Assertions.assertThrows(ELParseException.class, + () -> LiteFlowChainELBuilder.createChain() + .setChainId("chain3") + .setEL("THEN(s2)") + .build()); + + // 节点已卸载 + Assertions.assertFalse(FlowBus.containNode("s2")); + // 脚本已卸载 + Assertions.assertFalse(scriptExecutor.getNodeIds().contains("s2")); + } + + // 重载脚本 + @Test + public void testReloadScript() { + flowExecutor.reloadRule(); + String script = "defaultContext.setData(\"s1\",\"abc\");"; + FlowBus.reloadScript("s1", script); + LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); + DefaultContext context = response.getFirstContextBean(); + // 执行结果变更 + Assertions.assertEquals("abc", context.getData("s1")); + // 脚本变更 + Assertions.assertEquals(FlowBus.getNode("s1").getScript(), script); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-script-python-springboot/src/test/resources/remove/application.properties b/liteflow-testcase-el/liteflow-testcase-el-script-python-springboot/src/test/resources/remove/application.properties new file mode 100644 index 000000000..21b596255 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-script-python-springboot/src/test/resources/remove/application.properties @@ -0,0 +1 @@ +liteflow.rule-source=remove/flow.xml \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-script-python-springboot/src/test/resources/remove/flow.xml b/liteflow-testcase-el/liteflow-testcase-el-script-python-springboot/src/test/resources/remove/flow.xml new file mode 100644 index 000000000..0ca8f80fd --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-script-python-springboot/src/test/resources/remove/flow.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + THEN(s1); + + + + THEN(s2); + + \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-script-qlexpress-springboot/src/test/java/com/yomahub/liteflow/test/script/qlexpress/remove/LiteFlowQLExpressScriptRemoveELTest.java b/liteflow-testcase-el/liteflow-testcase-el-script-qlexpress-springboot/src/test/java/com/yomahub/liteflow/test/script/qlexpress/remove/LiteFlowQLExpressScriptRemoveELTest.java new file mode 100644 index 000000000..c86d6a2d3 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-script-qlexpress-springboot/src/test/java/com/yomahub/liteflow/test/script/qlexpress/remove/LiteFlowQLExpressScriptRemoveELTest.java @@ -0,0 +1,114 @@ +package com.yomahub.liteflow.test.script.qlexpress.remove; + +import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; +import com.yomahub.liteflow.core.FlowExecutor; +import com.yomahub.liteflow.enums.ScriptTypeEnum; +import com.yomahub.liteflow.exception.ELParseException; +import com.yomahub.liteflow.flow.FlowBus; +import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.script.ScriptExecutor; +import com.yomahub.liteflow.script.ScriptExecutorFactory; +import com.yomahub.liteflow.script.exception.ScriptLoadException; +import com.yomahub.liteflow.slot.DefaultContext; +import com.yomahub.liteflow.test.BaseTest; +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.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 测试脚本的卸载和重载功能 + * + * @author DaleLee + */ +@ExtendWith(SpringExtension.class) +@TestPropertySource(value = "classpath:/remove/application.properties") +@SpringBootTest(classes = LiteFlowQLExpressScriptRemoveELTest.class) +@EnableAutoConfiguration +public class LiteFlowQLExpressScriptRemoveELTest extends BaseTest { + + @Resource + private FlowExecutor flowExecutor; + + private ScriptExecutor scriptExecutor = ScriptExecutorFactory.loadInstance() + .getScriptExecutor(ScriptTypeEnum.QLEXPRESS.getDisplayName()); + + // 仅卸载脚本 + @Test + public void testUnload() { + flowExecutor.reloadRule(); + + // 获取节点id + List nodeIds = scriptExecutor.getNodeIds(); + Assertions.assertEquals(2, nodeIds.size()); + Assertions.assertTrue(nodeIds.contains("s1")); + Assertions.assertTrue(nodeIds.contains("s2")); + + // 保证脚本可以正常运行 + LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); + Assertions.assertTrue(response.isSuccess()); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertEquals(Integer.valueOf(6), context.getData("s1")); + + // 卸载脚本 + scriptExecutor.unLoad("s1"); + response = flowExecutor.execute2Resp("chain1", "arg"); + Assertions.assertFalse(response.isSuccess()); + Assertions.assertEquals(ScriptLoadException.class, response.getCause().getClass()); + Assertions.assertEquals("script for node[s1] is not loaded", response.getMessage()); + + // 脚本已卸载 + Assertions.assertFalse(scriptExecutor.getNodeIds().contains("s1")); + } + + // 卸载节点和脚本 + @Test + public void testRemove() { + flowExecutor.reloadRule(); + + // 保证脚本可以正常运行 + LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg"); + Assertions.assertTrue(response.isSuccess()); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertEquals(Integer.valueOf(5), context.getData("s2")); + + // 卸载节点 + FlowBus.removeNode("s2"); + + // 旧 chain 报脚本加载错误 + response = flowExecutor.execute2Resp("chain2", "arg"); + Assertions.assertEquals(ScriptLoadException.class, response.getCause().getClass()); + + // 新 chian 会找不到节点 + Assertions.assertThrows(ELParseException.class, + () -> LiteFlowChainELBuilder.createChain() + .setChainId("chain3") + .setEL("THEN(s2)") + .build()); + + // 节点已卸载 + Assertions.assertFalse(FlowBus.containNode("s2")); + // 脚本已卸载 + Assertions.assertFalse(scriptExecutor.getNodeIds().contains("s2")); + } + + // 重载脚本 + @Test + public void testReloadScript() { + flowExecutor.reloadRule(); + String script = "defaultContext.setData(\"s1\",\"abc\");"; + FlowBus.reloadScript("s1", script); + LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); + DefaultContext context = response.getFirstContextBean(); + // 执行结果变更 + Assertions.assertEquals("abc", context.getData("s1")); + // 脚本变更 + Assertions.assertEquals(FlowBus.getNode("s1").getScript(), script); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-script-qlexpress-springboot/src/test/resources/remove/application.properties b/liteflow-testcase-el/liteflow-testcase-el-script-qlexpress-springboot/src/test/resources/remove/application.properties new file mode 100644 index 000000000..21b596255 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-script-qlexpress-springboot/src/test/resources/remove/application.properties @@ -0,0 +1 @@ +liteflow.rule-source=remove/flow.xml \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-script-qlexpress-springboot/src/test/resources/remove/flow.xml b/liteflow-testcase-el/liteflow-testcase-el-script-qlexpress-springboot/src/test/resources/remove/flow.xml new file mode 100644 index 000000000..21e82c24b --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-script-qlexpress-springboot/src/test/resources/remove/flow.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + THEN(s1); + + + + THEN(s2); + + \ No newline at end of file