You've already forked FrameTour-BE
feat(puzzle): 增强拼图填充引擎功能
- 新增 requireRuleMatch 参数控制是否必须匹配规则 - 重构 DeviceCountConditionStrategy 支持两种匹配模式 - 移除已废弃的 DeviceCountRangeConditionStrategy - 引入 FillResult 类封装填充结果信息 - 优化条件上下文和数据源上下文的 extra 字段类型 - 更新相关测试用例和文档说明
This commit is contained in:
@@ -6,6 +6,10 @@ import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
@@ -130,7 +134,198 @@ class DeviceCountConditionStrategyTest {
|
||||
// When
|
||||
boolean result = strategy.evaluate(conditionValue, context);
|
||||
|
||||
// Then
|
||||
assertFalse(result); // 修改:deviceCount必须大于0
|
||||
}
|
||||
|
||||
// ==================== 模式2:指定列表数量匹配 ====================
|
||||
|
||||
@Test
|
||||
@DisplayName("模式2:当指定列表中恰好有期望数量的机位时应该返回true")
|
||||
void shouldReturnTrueWhenDeviceIdListMatchesCount() throws Exception {
|
||||
// Given
|
||||
String conditionValueJson = "{\"deviceCount\": 2, \"deviceIds\": [200, 300, 400]}";
|
||||
JsonNode conditionValue = objectMapper.readTree(conditionValueJson);
|
||||
|
||||
List<Long> contextDeviceIds = Arrays.asList(200L, 300L, 500L);
|
||||
ConditionContext context = ConditionContext.builder()
|
||||
.deviceCount(3)
|
||||
.deviceIds(contextDeviceIds)
|
||||
.build();
|
||||
|
||||
// When
|
||||
boolean result = strategy.evaluate(conditionValue, context);
|
||||
|
||||
// Then
|
||||
assertTrue(result);
|
||||
assertNotNull(context.getExtra());
|
||||
assertTrue(context.getExtra().containsKey("filteredDeviceIds"));
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Long> filteredIds = (List<Long>) context.getExtra().get("filteredDeviceIds");
|
||||
assertEquals(2, filteredIds.size());
|
||||
assertEquals(Arrays.asList(200L, 300L), filteredIds); // 保持配置顺序
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("模式2:当指定列表中的机位数量不足时应该返回false")
|
||||
void shouldReturnFalseWhenDeviceIdListCountInsufficient() throws Exception {
|
||||
// Given
|
||||
String conditionValueJson = "{\"deviceCount\": 3, \"deviceIds\": [200, 300, 400]}";
|
||||
JsonNode conditionValue = objectMapper.readTree(conditionValueJson);
|
||||
|
||||
List<Long> contextDeviceIds = Arrays.asList(200L, 300L, 500L);
|
||||
ConditionContext context = ConditionContext.builder()
|
||||
.deviceCount(3)
|
||||
.deviceIds(contextDeviceIds)
|
||||
.build();
|
||||
|
||||
// When
|
||||
boolean result = strategy.evaluate(conditionValue, context);
|
||||
|
||||
// Then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("模式2:当指定列表中的机位数量超过期望时应该返回false")
|
||||
void shouldReturnFalseWhenDeviceIdListCountExcessive() throws Exception {
|
||||
// Given
|
||||
String conditionValueJson = "{\"deviceCount\": 1, \"deviceIds\": [200, 300, 400]}";
|
||||
JsonNode conditionValue = objectMapper.readTree(conditionValueJson);
|
||||
|
||||
List<Long> contextDeviceIds = Arrays.asList(200L, 300L, 500L);
|
||||
ConditionContext context = ConditionContext.builder()
|
||||
.deviceCount(3)
|
||||
.deviceIds(contextDeviceIds)
|
||||
.build();
|
||||
|
||||
// When
|
||||
boolean result = strategy.evaluate(conditionValue, context);
|
||||
|
||||
// Then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("模式2:应该保持配置的机位顺序,不排序")
|
||||
void shouldPreserveDeviceIdOrderInMode2() throws Exception {
|
||||
// Given - 配置顺序为 400, 200, 300
|
||||
String conditionValueJson = "{\"deviceCount\": 3, \"deviceIds\": [400, 200, 300]}";
|
||||
JsonNode conditionValue = objectMapper.readTree(conditionValueJson);
|
||||
|
||||
List<Long> contextDeviceIds = Arrays.asList(200L, 300L, 400L);
|
||||
ConditionContext context = ConditionContext.builder()
|
||||
.deviceCount(3)
|
||||
.deviceIds(contextDeviceIds)
|
||||
.build();
|
||||
|
||||
// When
|
||||
boolean result = strategy.evaluate(conditionValue, context);
|
||||
|
||||
// Then
|
||||
assertTrue(result);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Long> filteredIds = (List<Long>) context.getExtra().get("filteredDeviceIds");
|
||||
assertEquals(Arrays.asList(400L, 200L, 300L), filteredIds); // 保持配置顺序,不是[200, 300, 400]
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("模式2:当deviceIds为空数组时应该返回false")
|
||||
void shouldReturnFalseWhenDeviceIdsIsEmptyArray() throws Exception {
|
||||
// Given
|
||||
String conditionValueJson = "{\"deviceCount\": 2, \"deviceIds\": []}";
|
||||
JsonNode conditionValue = objectMapper.readTree(conditionValueJson);
|
||||
|
||||
List<Long> contextDeviceIds = Arrays.asList(200L, 300L);
|
||||
ConditionContext context = ConditionContext.builder()
|
||||
.deviceCount(2)
|
||||
.deviceIds(contextDeviceIds)
|
||||
.build();
|
||||
|
||||
// When
|
||||
boolean result = strategy.evaluate(conditionValue, context);
|
||||
|
||||
// Then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("模式2:当deviceIds不是数组类型时应该返回false")
|
||||
void shouldReturnFalseWhenDeviceIdsIsNotArray() throws Exception {
|
||||
// Given
|
||||
String conditionValueJson = "{\"deviceCount\": 2, \"deviceIds\": \"not-an-array\"}";
|
||||
JsonNode conditionValue = objectMapper.readTree(conditionValueJson);
|
||||
|
||||
List<Long> contextDeviceIds = Arrays.asList(200L, 300L);
|
||||
ConditionContext context = ConditionContext.builder()
|
||||
.deviceCount(2)
|
||||
.deviceIds(contextDeviceIds)
|
||||
.build();
|
||||
|
||||
// When
|
||||
boolean result = strategy.evaluate(conditionValue, context);
|
||||
|
||||
// Then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("模式2:当context中没有deviceIds时应该返回false")
|
||||
void shouldReturnFalseWhenContextDeviceIdsIsNull() throws Exception {
|
||||
// Given
|
||||
String conditionValueJson = "{\"deviceCount\": 2, \"deviceIds\": [200, 300]}";
|
||||
JsonNode conditionValue = objectMapper.readTree(conditionValueJson);
|
||||
|
||||
ConditionContext context = ConditionContext.builder()
|
||||
.deviceCount(2)
|
||||
.deviceIds(null)
|
||||
.build();
|
||||
|
||||
// When
|
||||
boolean result = strategy.evaluate(conditionValue, context);
|
||||
|
||||
// Then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("模式2:当context中deviceIds为空列表时应该返回false")
|
||||
void shouldReturnFalseWhenContextDeviceIdsIsEmpty() throws Exception {
|
||||
// Given
|
||||
String conditionValueJson = "{\"deviceCount\": 2, \"deviceIds\": [200, 300]}";
|
||||
JsonNode conditionValue = objectMapper.readTree(conditionValueJson);
|
||||
|
||||
ConditionContext context = ConditionContext.builder()
|
||||
.deviceCount(2)
|
||||
.deviceIds(Collections.emptyList())
|
||||
.build();
|
||||
|
||||
// When
|
||||
boolean result = strategy.evaluate(conditionValue, context);
|
||||
|
||||
// Then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("模式2:当deviceCount为0时应该返回false")
|
||||
void shouldReturnFalseWhenDeviceCountIsZeroInMode2() throws Exception {
|
||||
// Given
|
||||
String conditionValueJson = "{\"deviceCount\": 0, \"deviceIds\": [200, 300]}";
|
||||
JsonNode conditionValue = objectMapper.readTree(conditionValueJson);
|
||||
|
||||
List<Long> contextDeviceIds = Arrays.asList(200L, 300L);
|
||||
ConditionContext context = ConditionContext.builder()
|
||||
.deviceCount(2)
|
||||
.deviceIds(contextDeviceIds)
|
||||
.build();
|
||||
|
||||
// When
|
||||
boolean result = strategy.evaluate(conditionValue, context);
|
||||
|
||||
// Then
|
||||
assertFalse(result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,190 +0,0 @@
|
||||
package com.ycwl.basic.puzzle.fill.condition;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* 机位数量范围匹配策略测试
|
||||
*/
|
||||
@DisplayName("机位数量范围匹配策略测试")
|
||||
class DeviceCountRangeConditionStrategyTest {
|
||||
|
||||
private DeviceCountRangeConditionStrategy strategy;
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
strategy = new DeviceCountRangeConditionStrategy();
|
||||
objectMapper = new ObjectMapper();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("应该返回正确的支持类型")
|
||||
void shouldReturnCorrectSupportedType() {
|
||||
assertEquals("DEVICE_COUNT_RANGE", strategy.getSupportedType());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("当机位数量在范围内时应该返回true")
|
||||
void shouldReturnTrueWhenDeviceCountInRange() throws Exception {
|
||||
// Given
|
||||
String conditionValueJson = "{\"minCount\": 2, \"maxCount\": 5}";
|
||||
JsonNode conditionValue = objectMapper.readTree(conditionValueJson);
|
||||
|
||||
ConditionContext context = ConditionContext.builder()
|
||||
.deviceCount(3)
|
||||
.build();
|
||||
|
||||
// When
|
||||
boolean result = strategy.evaluate(conditionValue, context);
|
||||
|
||||
// Then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("当机位数量等于最小值时应该返回true")
|
||||
void shouldReturnTrueWhenDeviceCountEqualsMin() throws Exception {
|
||||
// Given
|
||||
String conditionValueJson = "{\"minCount\": 2, \"maxCount\": 5}";
|
||||
JsonNode conditionValue = objectMapper.readTree(conditionValueJson);
|
||||
|
||||
ConditionContext context = ConditionContext.builder()
|
||||
.deviceCount(2)
|
||||
.build();
|
||||
|
||||
// When
|
||||
boolean result = strategy.evaluate(conditionValue, context);
|
||||
|
||||
// Then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("当机位数量等于最大值时应该返回true")
|
||||
void shouldReturnTrueWhenDeviceCountEqualsMax() throws Exception {
|
||||
// Given
|
||||
String conditionValueJson = "{\"minCount\": 2, \"maxCount\": 5}";
|
||||
JsonNode conditionValue = objectMapper.readTree(conditionValueJson);
|
||||
|
||||
ConditionContext context = ConditionContext.builder()
|
||||
.deviceCount(5)
|
||||
.build();
|
||||
|
||||
// When
|
||||
boolean result = strategy.evaluate(conditionValue, context);
|
||||
|
||||
// Then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("当机位数量小于最小值时应该返回false")
|
||||
void shouldReturnFalseWhenDeviceCountBelowMin() throws Exception {
|
||||
// Given
|
||||
String conditionValueJson = "{\"minCount\": 2, \"maxCount\": 5}";
|
||||
JsonNode conditionValue = objectMapper.readTree(conditionValueJson);
|
||||
|
||||
ConditionContext context = ConditionContext.builder()
|
||||
.deviceCount(1)
|
||||
.build();
|
||||
|
||||
// When
|
||||
boolean result = strategy.evaluate(conditionValue, context);
|
||||
|
||||
// Then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("当机位数量大于最大值时应该返回false")
|
||||
void shouldReturnFalseWhenDeviceCountAboveMax() throws Exception {
|
||||
// Given
|
||||
String conditionValueJson = "{\"minCount\": 2, \"maxCount\": 5}";
|
||||
JsonNode conditionValue = objectMapper.readTree(conditionValueJson);
|
||||
|
||||
ConditionContext context = ConditionContext.builder()
|
||||
.deviceCount(6)
|
||||
.build();
|
||||
|
||||
// When
|
||||
boolean result = strategy.evaluate(conditionValue, context);
|
||||
|
||||
// Then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("仅指定最小值时应该正确验证")
|
||||
void shouldValidateWithMinCountOnly() throws Exception {
|
||||
// Given
|
||||
String conditionValueJson = "{\"minCount\": 2}";
|
||||
JsonNode conditionValue = objectMapper.readTree(conditionValueJson);
|
||||
|
||||
ConditionContext context = ConditionContext.builder()
|
||||
.deviceCount(3)
|
||||
.build();
|
||||
|
||||
// When
|
||||
boolean result = strategy.evaluate(conditionValue, context);
|
||||
|
||||
// Then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("仅指定最大值时应该正确验证")
|
||||
void shouldValidateWithMaxCountOnly() throws Exception {
|
||||
// Given
|
||||
String conditionValueJson = "{\"maxCount\": 5}";
|
||||
JsonNode conditionValue = objectMapper.readTree(conditionValueJson);
|
||||
|
||||
ConditionContext context = ConditionContext.builder()
|
||||
.deviceCount(3)
|
||||
.build();
|
||||
|
||||
// When
|
||||
boolean result = strategy.evaluate(conditionValue, context);
|
||||
|
||||
// Then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("当conditionValue为null时应该返回false")
|
||||
void shouldReturnFalseWhenConditionValueIsNull() {
|
||||
// Given
|
||||
ConditionContext context = ConditionContext.builder()
|
||||
.deviceCount(3)
|
||||
.build();
|
||||
|
||||
// When
|
||||
boolean result = strategy.evaluate(null, context);
|
||||
|
||||
// Then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("当context中deviceCount为null时应该返回false")
|
||||
void shouldReturnFalseWhenContextDeviceCountIsNull() throws Exception {
|
||||
// Given
|
||||
String conditionValueJson = "{\"minCount\": 2, \"maxCount\": 5}";
|
||||
JsonNode conditionValue = objectMapper.readTree(conditionValueJson);
|
||||
|
||||
ConditionContext context = ConditionContext.builder()
|
||||
.deviceCount(null)
|
||||
.build();
|
||||
|
||||
// When
|
||||
boolean result = strategy.evaluate(conditionValue, context);
|
||||
|
||||
// Then
|
||||
assertFalse(result);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user