diff --git a/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/ProxyTest.java b/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/ai/proxy/ProxyTest.java similarity index 76% rename from liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/ProxyTest.java rename to liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/ai/proxy/ProxyTest.java index d3c32fd69..556fb1fdf 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/ProxyTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/ai/proxy/ProxyTest.java @@ -1,8 +1,9 @@ -package com.yomahub.liteflow.test; +package com.yomahub.liteflow.test.ai.proxy; import com.yomahub.liteflow.ai.context.ChatContext; import com.yomahub.liteflow.core.FlowExecutor; import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.slot.DefaultContext; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; @@ -19,10 +20,10 @@ import javax.annotation.Resource; * @since TODO */ -@TestPropertySource(value = "classpath:application.yaml") +@TestPropertySource("classpath:/proxy/application.yaml") @SpringBootTest(classes = {ProxyTest.class}) @EnableAutoConfiguration -@ComponentScan({"com.yomahub.liteflow.test.cmp"}) +@ComponentScan({"com.yomahub.liteflow.test.ai.proxy.cmp"}) public class ProxyTest { @Resource @@ -30,7 +31,7 @@ public class ProxyTest { @Test public void testProxy() { - LiteflowResponse liteflowResponse = flowExecutor.execute2Resp("chain1", null, ChatContext.class); + LiteflowResponse liteflowResponse = flowExecutor.execute2Resp("chain1", null, ChatContext.class, DefaultContext.class); Assertions.assertTrue(liteflowResponse.isSuccess()); } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/cmp/ACmp.java b/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/ai/proxy/cmp/ACmp.java similarity index 87% rename from liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/cmp/ACmp.java rename to liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/ai/proxy/cmp/ACmp.java index 9f0eb33cf..4e7d59d56 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/cmp/ACmp.java +++ b/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/ai/proxy/cmp/ACmp.java @@ -1,4 +1,4 @@ -package com.yomahub.liteflow.test.cmp; +package com.yomahub.liteflow.test.ai.proxy.cmp; import com.yomahub.liteflow.core.NodeComponent; import org.springframework.stereotype.Component; diff --git a/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/cmp/AICmp.java b/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/ai/proxy/cmp/AICmp.java similarity index 89% rename from liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/cmp/AICmp.java rename to liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/ai/proxy/cmp/AICmp.java index 2b9400d52..0c69b821a 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/cmp/AICmp.java +++ b/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/ai/proxy/cmp/AICmp.java @@ -1,4 +1,4 @@ -package com.yomahub.liteflow.test.cmp; +package com.yomahub.liteflow.test.ai.proxy.cmp; import com.yomahub.liteflow.ai.annotation.*; import com.yomahub.liteflow.ai.domain.enums.ResponseType; @@ -18,7 +18,7 @@ import com.yomahub.liteflow.ai.domain.enums.ResponseType; model = "qwen3:32b" ) @AIChat( - systemPrompt = "classpath:system_prompt.txt", + systemPrompt = "classpath:proxy/system_prompt.txt", userPrompt = "{{question}}, {{answer}}" ) @AIInput( diff --git a/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/cmp/BCmp.java b/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/ai/proxy/cmp/BCmp.java similarity index 87% rename from liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/cmp/BCmp.java rename to liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/ai/proxy/cmp/BCmp.java index f7ee7be45..c00097127 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/cmp/BCmp.java +++ b/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/ai/proxy/cmp/BCmp.java @@ -1,4 +1,4 @@ -package com.yomahub.liteflow.test.cmp; +package com.yomahub.liteflow.test.ai.proxy.cmp; import com.yomahub.liteflow.core.NodeComponent; import org.springframework.stereotype.Component; diff --git a/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/cmp/Output.java b/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/ai/proxy/cmp/Output.java similarity index 88% rename from liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/cmp/Output.java rename to liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/ai/proxy/cmp/Output.java index 16828270e..e9c714c62 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/cmp/Output.java +++ b/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/ai/proxy/cmp/Output.java @@ -1,4 +1,4 @@ -package com.yomahub.liteflow.test.cmp; +package com.yomahub.liteflow.test.ai.proxy.cmp; /** * 测试结构化输出使用 diff --git a/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/ai/util/SetUtilTest.java b/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/ai/util/SetUtilTest.java new file mode 100644 index 000000000..8dcceb527 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/ai/util/SetUtilTest.java @@ -0,0 +1,158 @@ +package com.yomahub.liteflow.test.ai.util; + +import com.yomahub.liteflow.ai.util.SetUtil; +import com.yomahub.liteflow.ai.util.TriState; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.params.provider.Arguments.arguments; + +/** + * SetUtil 工具类测试 + * + * @author 苍镜月 + * @since TODO + */ + +@DisplayName("SetUtil 工具类测试") +class SetUtilTest { + + // --- 为参数化测试提供数据 --- + + private static final String NOT_PRESENT_METHOD_SOURCE = "com.yomahub.liteflow.test.ai.util.SetUtilTest#provideNotPresentValues"; + private static final String PRESENT_METHOD_SOURCE = "com.yomahub.liteflow.test.ai.util.SetUtilTest#providePresentValues"; + + /** + * 提供被认为是 "not present" (不存在/为空/为默认值) 的各种值 + */ + static Stream provideNotPresentValues() { + return Stream.of( + arguments((Object) null), + arguments(""), + arguments(" "), + arguments(new ArrayList<>()), + arguments(Collections.emptyMap()), + arguments((Object) new String[0]), + arguments((Object) new int[0]), + arguments(TriState.UNSET), + arguments(-1), + arguments(-1L), + arguments(-1.0), + arguments(-1.0f) + ); + } + + + /** + * 提供被认为是 "present" (存在/有效) 的各种值 + */ + static Stream providePresentValues() { + Map presentMap = new HashMap<>(); + presentMap.put("key", 1); + + return Stream.of( + arguments("hello"), + arguments(" a "), + arguments(Arrays.asList(1, 2)), + arguments(presentMap), + arguments((Object) new String[]{"a"}), + arguments((Object) new int[]{1}), + arguments(new Object()), + arguments(TriState.TRUE), + arguments(0), + arguments(1), + arguments(0L), + arguments(0.0), + arguments(0.0f) + ); + } + + + @Nested + @DisplayName("核心判断方法:isPresent 和 isNotPresent") + class IsPresentAndNotPresentTests { + + @ParameterizedTest + @MethodSource(NOT_PRESENT_METHOD_SOURCE) + @DisplayName("isNotPresent: 对于 null、空集合或默认值应返回 true") + void testIsNotPresent_shouldReturnTrue_forEmptyOrDefaultValues(Object value) { + assertTrue(SetUtil.isNotPresent(value), "值 " + value + " 应被视为 not present"); + } + + @ParameterizedTest + @MethodSource(PRESENT_METHOD_SOURCE) + @DisplayName("isNotPresent: 对于有效值应返回 false") + void testIsNotPresent_shouldReturnFalse_forPresentValues(Object value) { + assertFalse(SetUtil.isNotPresent(value), "值 " + value + " 应被视为 present"); + } + + @ParameterizedTest + @MethodSource(PRESENT_METHOD_SOURCE) + @DisplayName("isPresent: 对于有效值应返回 true") + void testIsPresent_shouldReturnTrue_forPresentValues(Object value) { + assertTrue(SetUtil.isPresent(value), "值 " + value + " 应被视为 present"); + } + + @ParameterizedTest + @MethodSource(NOT_PRESENT_METHOD_SOURCE) + @DisplayName("isPresent: 对于 null、空集合或默认值应返回 false") + void testIsPresent_shouldReturnFalse_forEmptyOrDefaultValues(Object value) { + assertFalse(SetUtil.isPresent(value), "值 " + value + " 应被视为 not present"); + } + } + + @Nested + @DisplayName("消费方法: setIfPresent") + class SetIfPresentTests { + + @ParameterizedTest + @MethodSource(PRESENT_METHOD_SOURCE) + @DisplayName("当值存在时,应执行 Consumer") + void shouldExecuteConsumer_whenValueIsPresent(Object presentValue) { + AtomicBoolean executed = new AtomicBoolean(false); + SetUtil.setIfPresent(v -> executed.set(true), presentValue); + assertTrue(executed.get(), "当值为 " + presentValue + " 时,Consumer 应该被执行"); + } + + @ParameterizedTest + @MethodSource(NOT_PRESENT_METHOD_SOURCE) + @DisplayName("当值不存在时,不应执行 Consumer") + void shouldNotExecuteConsumer_whenValueIsNotPresent(Object notPresentValue) { + AtomicBoolean executed = new AtomicBoolean(false); + SetUtil.setIfPresent(v -> executed.set(true), notPresentValue); + assertFalse(executed.get(), "当值为 " + notPresentValue + " 时,Consumer 不应该被执行"); + } + } + + @Nested + @DisplayName("消费方法: setIfNotPresent") + class SetIfNotPresentTests { + + @ParameterizedTest + @MethodSource(NOT_PRESENT_METHOD_SOURCE) + @DisplayName("当值不存在时,应执行 Consumer") + void shouldExecuteConsumer_whenValueIsNotPresent(Object notPresentValue) { + AtomicBoolean executed = new AtomicBoolean(false); + SetUtil.setIfNotPresent(v -> executed.set(true), notPresentValue); + assertTrue(executed.get(), "当值为 " + notPresentValue + " 时,Consumer 应该被执行"); + } + + @ParameterizedTest + @MethodSource(PRESENT_METHOD_SOURCE) + @DisplayName("当值存在时,不应执行 Consumer") + void shouldNotExecuteConsumer_whenValueIsPresent(Object presentValue) { + AtomicBoolean executed = new AtomicBoolean(false); + SetUtil.setIfNotPresent(v -> executed.set(true), presentValue); + assertFalse(executed.get(), "当值为 " + presentValue + " 时,Consumer 不应该被执行"); + } + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/resources/application.yaml b/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/resources/application.yaml deleted file mode 100644 index 83bbab96f..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/resources/application.yaml +++ /dev/null @@ -1,6 +0,0 @@ -liteflow: - rule-source: flow.el.xml - ai: - base-packages: - - com.yomahub.liteflow.test.cmp - enable: true \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/resources/proxy/application.yaml b/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/resources/proxy/application.yaml new file mode 100644 index 000000000..8586c466a --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/resources/proxy/application.yaml @@ -0,0 +1,6 @@ +liteflow: + rule-source: proxy/flow.el.xml + ai: + base-packages: + - com.yomahub.liteflow.test.ai.proxy.cmp + enable: true \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/resources/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/resources/proxy/flow.el.xml similarity index 100% rename from liteflow-testcase-el/liteflow-testcase-el-ai/src/test/resources/flow.el.xml rename to liteflow-testcase-el/liteflow-testcase-el-ai/src/test/resources/proxy/flow.el.xml diff --git a/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/resources/system_prompt.txt b/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/resources/proxy/system_prompt.txt similarity index 100% rename from liteflow-testcase-el/liteflow-testcase-el-ai/src/test/resources/system_prompt.txt rename to liteflow-testcase-el/liteflow-testcase-el-ai/src/test/resources/proxy/system_prompt.txt