mirror of
https://gitee.com/zhijiantianya/ruoyi-vue-pro.git
synced 2025-12-26 08:26:44 +08:00
feat:【IoT 物联网】场景联动规则匹配器单元测试
This commit is contained in:
parent
fb35807ebf
commit
7661c7165c
@ -2,18 +2,11 @@ package cn.iocoder.yudao.module.iot.service.rule.scene;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.collection.ListUtil;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.text.CharPool;
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils;
|
||||
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
|
||||
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
|
||||
import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotSceneRulePageReqVO;
|
||||
@ -23,7 +16,6 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
|
||||
import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotSceneRuleMapper;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionOperatorEnum;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
|
||||
import cn.iocoder.yudao.module.iot.framework.job.core.IotSchedulerManager;
|
||||
import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
|
||||
@ -36,12 +28,9 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
|
||||
import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.RULE_SCENE_NOT_EXISTS;
|
||||
|
||||
@ -353,65 +342,6 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO @puhui999:下面还需要么?
|
||||
/**
|
||||
* 判断触发器的条件参数是否匹配
|
||||
*
|
||||
* @param message 设备消息
|
||||
* @param condition 触发条件
|
||||
* @param sceneRule 规则场景(用于日志,无其它作用)
|
||||
* @param trigger 触发器(用于日志,无其它作用)
|
||||
* @return 是否匹配
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "DataFlowIssue"})
|
||||
private boolean isTriggerConditionParameterMatched(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition,
|
||||
IotSceneRuleDO sceneRule, IotSceneRuleDO.Trigger trigger) {
|
||||
// 1.1 校验操作符是否合法
|
||||
IotSceneRuleConditionOperatorEnum operator =
|
||||
IotSceneRuleConditionOperatorEnum.operatorOf(condition.getOperator());
|
||||
if (operator == null) {
|
||||
log.error("[isTriggerConditionParameterMatched][规则场景编号({}) 的触发器({}) 存在错误的操作符({})]",
|
||||
sceneRule.getId(), trigger, condition.getOperator());
|
||||
return false;
|
||||
}
|
||||
// 1.2 校验消息是否包含对应的值
|
||||
String messageValue = MapUtil.getStr((Map<String, Object>) message.getData(), condition.getIdentifier());
|
||||
if (messageValue == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2.1 构建 Spring 表达式的变量
|
||||
Map<String, Object> springExpressionVariables = new HashMap<>();
|
||||
try {
|
||||
springExpressionVariables.put(IotSceneRuleConditionOperatorEnum.SPRING_EXPRESSION_SOURCE, messageValue);
|
||||
springExpressionVariables.put(IotSceneRuleConditionOperatorEnum.SPRING_EXPRESSION_VALUE, condition.getParam());
|
||||
List<String> parameterValues = StrUtil.splitTrim(condition.getParam(), CharPool.COMMA);
|
||||
springExpressionVariables.put(IotSceneRuleConditionOperatorEnum.SPRING_EXPRESSION_VALUE_LIST, parameterValues);
|
||||
// 特殊:解决数字的比较。因为 Spring 是基于它的 compareTo 方法,对数字的比较存在问题!
|
||||
if (ObjectUtils.equalsAny(operator, IotSceneRuleConditionOperatorEnum.BETWEEN,
|
||||
IotSceneRuleConditionOperatorEnum.NOT_BETWEEN,
|
||||
IotSceneRuleConditionOperatorEnum.GREATER_THAN,
|
||||
IotSceneRuleConditionOperatorEnum.GREATER_THAN_OR_EQUALS,
|
||||
IotSceneRuleConditionOperatorEnum.LESS_THAN,
|
||||
IotSceneRuleConditionOperatorEnum.LESS_THAN_OR_EQUALS)
|
||||
&& NumberUtil.isNumber(messageValue)
|
||||
&& NumberUtils.isAllNumber(parameterValues)) {
|
||||
springExpressionVariables.put(IotSceneRuleConditionOperatorEnum.SPRING_EXPRESSION_SOURCE,
|
||||
NumberUtil.parseDouble(messageValue));
|
||||
springExpressionVariables.put(IotSceneRuleConditionOperatorEnum.SPRING_EXPRESSION_VALUE,
|
||||
NumberUtil.parseDouble(condition.getParam()));
|
||||
springExpressionVariables.put(IotSceneRuleConditionOperatorEnum.SPRING_EXPRESSION_VALUE_LIST,
|
||||
convertList(parameterValues, NumberUtil::parseDouble));
|
||||
}
|
||||
// 2.2 计算 Spring 表达式
|
||||
return (Boolean) SpringExpressionUtils.parseExpression(operator.getSpringExpression(), springExpressionVariables);
|
||||
} catch (Exception e) {
|
||||
log.error("[isTriggerConditionParameterMatched][消息({}) 规则场景编号({}) 的触发器({}) 的匹配表达式({}/{}) 计算异常]",
|
||||
message, sceneRule.getId(), trigger, operator, springExpressionVariables, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行规则场景的动作
|
||||
*
|
||||
|
||||
@ -1,190 +0,0 @@
|
||||
package cn.iocoder.yudao.module.iot.service.rule.scene.matcher;
|
||||
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
|
||||
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
|
||||
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.trigger.*;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* IoT 场景规则触发器匹配器测试类
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
public class IotSceneRuleTriggerMatcherTest extends BaseMockitoUnitTest {
|
||||
|
||||
// TODO @puhui999:public 都加下哈;
|
||||
|
||||
private IotSceneRuleMatcherManager matcherManager;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
// 创建所有匹配器实例
|
||||
List<IotSceneRuleMatcher> matchers = Arrays.asList(
|
||||
new DeviceStateUpdateTriggerMatcher(),
|
||||
new DevicePropertyPostTriggerMatcher(),
|
||||
new DeviceEventPostTriggerMatcher(),
|
||||
new DeviceServiceInvokeTriggerMatcher(),
|
||||
new TimerTriggerMatcher()
|
||||
);
|
||||
|
||||
// 初始化匹配器管理器
|
||||
matcherManager = new IotSceneRuleMatcherManager(matchers);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDeviceStateUpdateTriggerMatcher() {
|
||||
// 1. 准备测试数据
|
||||
IotDeviceMessage message = IotDeviceMessage.builder()
|
||||
.requestId("test-001")
|
||||
.method("thing.state.update") // TODO @puhui999:这里的枚举;
|
||||
.data(1) // 在线状态 TODO @puhui999:这里的枚举;
|
||||
.build();
|
||||
|
||||
IotSceneRuleDO.Trigger trigger = new IotSceneRuleDO.Trigger();
|
||||
trigger.setType(IotSceneRuleTriggerTypeEnum.DEVICE_STATE_UPDATE.getType());
|
||||
trigger.setOperator("="); // TODO @puhui999:这里的枚举;下面也是类似;
|
||||
trigger.setValue("1");
|
||||
|
||||
// 2. 执行测试
|
||||
boolean matched = matcherManager.isMatched(message, trigger);
|
||||
|
||||
// 3. 验证结果
|
||||
assertTrue(matched, "设备状态更新触发器应该匹配");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDevicePropertyPostTriggerMatcher() {
|
||||
// 1. 准备测试数据
|
||||
HashMap<String, Object> params = new HashMap<>();
|
||||
IotDeviceMessage message = IotDeviceMessage.builder()
|
||||
.requestId("test-002")
|
||||
.method("thing.property.post")
|
||||
.data(25.5) // 温度值
|
||||
.params(params)
|
||||
.build();
|
||||
// 模拟标识符
|
||||
params.put("identifier", "temperature");
|
||||
|
||||
IotSceneRuleDO.Trigger trigger = new IotSceneRuleDO.Trigger();
|
||||
trigger.setType(IotSceneRuleTriggerTypeEnum.DEVICE_PROPERTY_POST.getType());
|
||||
trigger.setIdentifier("temperature");
|
||||
trigger.setOperator(">");
|
||||
trigger.setValue("20");
|
||||
|
||||
// 2. 执行测试
|
||||
boolean matched = matcherManager.isMatched(message, trigger);
|
||||
|
||||
// 3. 验证结果
|
||||
assertTrue(matched, "设备属性上报触发器应该匹配");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDeviceEventPostTriggerMatcher() {
|
||||
// 1. 准备测试数据
|
||||
HashMap<String, Object> params = new HashMap<>();
|
||||
IotDeviceMessage message = IotDeviceMessage.builder()
|
||||
.requestId("test-003")
|
||||
.method("thing.event.post")
|
||||
.data("alarm_data")
|
||||
.params(params)
|
||||
.build();
|
||||
// 模拟标识符
|
||||
params.put("identifier", "high_temperature_alarm");
|
||||
|
||||
IotSceneRuleDO.Trigger trigger = new IotSceneRuleDO.Trigger();
|
||||
trigger.setType(IotSceneRuleTriggerTypeEnum.DEVICE_EVENT_POST.getType());
|
||||
trigger.setIdentifier("high_temperature_alarm");
|
||||
|
||||
// 2. 执行测试
|
||||
boolean matched = matcherManager.isMatched(message, trigger);
|
||||
|
||||
// 3. 验证结果
|
||||
assertTrue(matched, "设备事件上报触发器应该匹配");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDeviceServiceInvokeTriggerMatcher() {
|
||||
// 1. 准备测试数据
|
||||
HashMap<String, Object> params = new HashMap<>();
|
||||
IotDeviceMessage message = IotDeviceMessage.builder()
|
||||
.requestId("test-004")
|
||||
.method("thing.service.invoke")
|
||||
.msg("alarm_data")
|
||||
.params(params)
|
||||
.build();
|
||||
// 模拟标识符
|
||||
params.put("identifier", "restart_device");
|
||||
|
||||
IotSceneRuleDO.Trigger trigger = new IotSceneRuleDO.Trigger();
|
||||
trigger.setType(IotSceneRuleTriggerTypeEnum.DEVICE_SERVICE_INVOKE.getType());
|
||||
trigger.setIdentifier("restart_device");
|
||||
|
||||
// 2. 执行测试
|
||||
boolean matched = matcherManager.isMatched(message, trigger);
|
||||
|
||||
// 3. 验证结果
|
||||
assertTrue(matched, "设备服务调用触发器应该匹配");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTimerTriggerMatcher() {
|
||||
// 1. 准备测试数据
|
||||
IotDeviceMessage message = IotDeviceMessage.builder()
|
||||
.requestId("test-005")
|
||||
.method("timer.trigger") // 定时触发器不依赖具体消息方法
|
||||
.build();
|
||||
|
||||
IotSceneRuleDO.Trigger trigger = new IotSceneRuleDO.Trigger();
|
||||
trigger.setType(IotSceneRuleTriggerTypeEnum.TIMER.getType());
|
||||
trigger.setCronExpression("0 0 12 * * ?"); // 每天中午12点
|
||||
|
||||
// 2. 执行测试
|
||||
boolean matched = matcherManager.isMatched(message, trigger);
|
||||
|
||||
// 3. 验证结果
|
||||
assertTrue(matched, "定时触发器应该匹配");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInvalidTriggerType() {
|
||||
// 1. 准备测试数据
|
||||
IotDeviceMessage message = IotDeviceMessage.builder()
|
||||
.requestId("test-006")
|
||||
.method("unknown.method")
|
||||
.build();
|
||||
|
||||
IotSceneRuleDO.Trigger trigger = new IotSceneRuleDO.Trigger();
|
||||
trigger.setType(999); // 无效的触发器类型
|
||||
|
||||
// 2. 执行测试
|
||||
boolean matched = matcherManager.isMatched(message, trigger);
|
||||
|
||||
// 3. 验证结果
|
||||
assertFalse(matched, "无效的触发器类型应该不匹配");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetSupportedTriggerTypes() {
|
||||
// 1. 执行测试
|
||||
var supportedTypes = matcherManager.getSupportedTriggerTypes();
|
||||
|
||||
// 2. 验证结果
|
||||
assertNotNull(supportedTypes);
|
||||
assertEquals(5, supportedTypes.size());
|
||||
assertTrue(supportedTypes.contains(IotSceneRuleTriggerTypeEnum.DEVICE_STATE_UPDATE));
|
||||
assertTrue(supportedTypes.contains(IotSceneRuleTriggerTypeEnum.DEVICE_PROPERTY_POST));
|
||||
assertTrue(supportedTypes.contains(IotSceneRuleTriggerTypeEnum.DEVICE_EVENT_POST));
|
||||
assertTrue(supportedTypes.contains(IotSceneRuleTriggerTypeEnum.DEVICE_SERVICE_INVOKE));
|
||||
assertTrue(supportedTypes.contains(IotSceneRuleTriggerTypeEnum.TIMER));
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,321 @@
|
||||
package cn.iocoder.yudao.module.iot.service.rule.scene.matcher.condition;
|
||||
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
|
||||
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionOperatorEnum;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionTypeEnum;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* {@link CurrentTimeConditionMatcher} 的单元测试类
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
public class CurrentTimeConditionMatcherTest extends BaseMockitoUnitTest {
|
||||
|
||||
private CurrentTimeConditionMatcher matcher;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
matcher = new CurrentTimeConditionMatcher();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSupportedConditionType() {
|
||||
// when & then
|
||||
assertEquals(IotSceneRuleConditionTypeEnum.CURRENT_TIME, matcher.getSupportedConditionType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPriority() {
|
||||
// when & then
|
||||
assertEquals(40, matcher.getPriority());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsEnabled() {
|
||||
// when & then
|
||||
assertTrue(matcher.isEnabled());
|
||||
}
|
||||
|
||||
// ========== 时间戳条件测试 ==========
|
||||
|
||||
@Test
|
||||
public void testIsMatched_DateTimeGreaterThan_Success() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
long pastTimestamp = LocalDateTime.now().minusHours(1).toEpochSecond(ZoneOffset.of("+8"));
|
||||
IotSceneRuleDO.TriggerCondition condition = createDateTimeCondition(
|
||||
IotSceneRuleConditionOperatorEnum.DATE_TIME_GREATER_THAN.getOperator(),
|
||||
String.valueOf(pastTimestamp)
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_DateTimeGreaterThan_Failure() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
long futureTimestamp = LocalDateTime.now().plusHours(1).toEpochSecond(ZoneOffset.of("+8"));
|
||||
IotSceneRuleDO.TriggerCondition condition = createDateTimeCondition(
|
||||
IotSceneRuleConditionOperatorEnum.DATE_TIME_GREATER_THAN.getOperator(),
|
||||
String.valueOf(futureTimestamp)
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_DateTimeLessThan_Success() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
long futureTimestamp = LocalDateTime.now().plusHours(1).toEpochSecond(ZoneOffset.of("+8"));
|
||||
IotSceneRuleDO.TriggerCondition condition = createDateTimeCondition(
|
||||
IotSceneRuleConditionOperatorEnum.DATE_TIME_LESS_THAN.getOperator(),
|
||||
String.valueOf(futureTimestamp)
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_DateTimeBetween_Success() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
long startTimestamp = LocalDateTime.now().minusHours(1).toEpochSecond(ZoneOffset.of("+8"));
|
||||
long endTimestamp = LocalDateTime.now().plusHours(1).toEpochSecond(ZoneOffset.of("+8"));
|
||||
IotSceneRuleDO.TriggerCondition condition = createDateTimeCondition(
|
||||
IotSceneRuleConditionOperatorEnum.DATE_TIME_BETWEEN.getOperator(),
|
||||
startTimestamp + "," + endTimestamp
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_DateTimeBetween_Failure() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
long startTimestamp = LocalDateTime.now().plusHours(1).toEpochSecond(ZoneOffset.of("+8"));
|
||||
long endTimestamp = LocalDateTime.now().plusHours(2).toEpochSecond(ZoneOffset.of("+8"));
|
||||
IotSceneRuleDO.TriggerCondition condition = createDateTimeCondition(
|
||||
IotSceneRuleConditionOperatorEnum.DATE_TIME_BETWEEN.getOperator(),
|
||||
startTimestamp + "," + endTimestamp
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
// ========== 当日时间条件测试 ==========
|
||||
|
||||
@Test
|
||||
public void testIsMatched_TimeGreaterThan_EarlyMorning() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
IotSceneRuleDO.TriggerCondition condition = createTimeCondition(
|
||||
IotSceneRuleConditionOperatorEnum.TIME_GREATER_THAN.getOperator(),
|
||||
"06:00:00" // 早上6点
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
// 结果取决于当前时间,如果当前时间大于6点则为true
|
||||
assertNotNull(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_TimeLessThan_LateNight() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
IotSceneRuleDO.TriggerCondition condition = createTimeCondition(
|
||||
IotSceneRuleConditionOperatorEnum.TIME_LESS_THAN.getOperator(),
|
||||
"23:59:59" // 晚上11点59分59秒
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
// 大部分情况下应该为true,除非在午夜前1秒运行测试
|
||||
assertNotNull(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_TimeBetween_AllDay() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
IotSceneRuleDO.TriggerCondition condition = createTimeCondition(
|
||||
IotSceneRuleConditionOperatorEnum.TIME_BETWEEN.getOperator(),
|
||||
"00:00:00,23:59:59" // 全天
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertTrue(result); // 全天范围应该总是匹配
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_TimeBetween_WorkingHours() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
IotSceneRuleDO.TriggerCondition condition = createTimeCondition(
|
||||
IotSceneRuleConditionOperatorEnum.TIME_BETWEEN.getOperator(),
|
||||
"09:00:00,17:00:00" // 工作时间
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
// 结果取决于当前时间是否在工作时间内
|
||||
assertNotNull(result);
|
||||
}
|
||||
|
||||
// ========== 异常情况测试 ==========
|
||||
|
||||
@Test
|
||||
public void testIsMatched_NullCondition() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, null);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_NullConditionType() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
IotSceneRuleDO.TriggerCondition condition = new IotSceneRuleDO.TriggerCondition();
|
||||
condition.setType(null);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_InvalidOperator() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
IotSceneRuleDO.TriggerCondition condition = new IotSceneRuleDO.TriggerCondition();
|
||||
condition.setType(IotSceneRuleConditionTypeEnum.CURRENT_TIME.getType());
|
||||
condition.setOperator("invalid_operator");
|
||||
condition.setParam("12:00:00");
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_InvalidTimeFormat() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
IotSceneRuleDO.TriggerCondition condition = createTimeCondition(
|
||||
IotSceneRuleConditionOperatorEnum.TIME_GREATER_THAN.getOperator(),
|
||||
"invalid-time-format"
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_InvalidTimestampFormat() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
IotSceneRuleDO.TriggerCondition condition = createDateTimeCondition(
|
||||
IotSceneRuleConditionOperatorEnum.DATE_TIME_GREATER_THAN.getOperator(),
|
||||
"invalid-timestamp"
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_InvalidBetweenFormat() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
IotSceneRuleDO.TriggerCondition condition = createTimeCondition(
|
||||
IotSceneRuleConditionOperatorEnum.TIME_BETWEEN.getOperator(),
|
||||
"09:00:00" // 缺少结束时间
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
// ========== 辅助方法 ==========
|
||||
|
||||
/**
|
||||
* 创建日期时间条件
|
||||
*/
|
||||
private IotSceneRuleDO.TriggerCondition createDateTimeCondition(String operator, String param) {
|
||||
IotSceneRuleDO.TriggerCondition condition = new IotSceneRuleDO.TriggerCondition();
|
||||
condition.setType(IotSceneRuleConditionTypeEnum.CURRENT_TIME.getType());
|
||||
condition.setOperator(operator);
|
||||
condition.setParam(param);
|
||||
return condition;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建当日时间条件
|
||||
*/
|
||||
private IotSceneRuleDO.TriggerCondition createTimeCondition(String operator, String param) {
|
||||
IotSceneRuleDO.TriggerCondition condition = new IotSceneRuleDO.TriggerCondition();
|
||||
condition.setType(IotSceneRuleConditionTypeEnum.CURRENT_TIME.getType());
|
||||
condition.setOperator(operator);
|
||||
condition.setParam(param);
|
||||
return condition;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,391 @@
|
||||
package cn.iocoder.yudao.module.iot.service.rule.scene.matcher.condition;
|
||||
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
|
||||
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionOperatorEnum;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionTypeEnum;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* {@link DevicePropertyConditionMatcher} 的单元测试类
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
public class DevicePropertyConditionMatcherTest extends BaseMockitoUnitTest {
|
||||
|
||||
private DevicePropertyConditionMatcher matcher;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
matcher = new DevicePropertyConditionMatcher();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSupportedConditionType() {
|
||||
// when & then
|
||||
assertEquals(IotSceneRuleConditionTypeEnum.DEVICE_PROPERTY, matcher.getSupportedConditionType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPriority() {
|
||||
// when & then
|
||||
assertEquals(20, matcher.getPriority());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsEnabled() {
|
||||
// when & then
|
||||
assertTrue(matcher.isEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_TemperatureEquals() {
|
||||
// given
|
||||
Map<String, Object> properties = MapUtil.of("temperature", 25.5);
|
||||
IotDeviceMessage message = createDeviceMessage(properties);
|
||||
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
|
||||
"temperature",
|
||||
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
|
||||
"25.5"
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_HumidityGreaterThan() {
|
||||
// given
|
||||
Map<String, Object> properties = MapUtil.of("humidity", 75);
|
||||
IotDeviceMessage message = createDeviceMessage(properties);
|
||||
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
|
||||
"humidity",
|
||||
IotSceneRuleConditionOperatorEnum.GREATER_THAN.getOperator(),
|
||||
"70"
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_PressureLessThan() {
|
||||
// given
|
||||
Map<String, Object> properties = MapUtil.of("pressure", 1010.5);
|
||||
IotDeviceMessage message = createDeviceMessage(properties);
|
||||
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
|
||||
"pressure",
|
||||
IotSceneRuleConditionOperatorEnum.LESS_THAN.getOperator(),
|
||||
"1020"
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_StatusNotEquals() {
|
||||
// given
|
||||
Map<String, Object> properties = MapUtil.of("status", "active");
|
||||
IotDeviceMessage message = createDeviceMessage(properties);
|
||||
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
|
||||
"status",
|
||||
IotSceneRuleConditionOperatorEnum.NOT_EQUALS.getOperator(),
|
||||
"inactive"
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_PropertyMismatch() {
|
||||
// given
|
||||
Map<String, Object> properties = MapUtil.of("temperature", 15.0);
|
||||
IotDeviceMessage message = createDeviceMessage(properties);
|
||||
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
|
||||
"temperature",
|
||||
IotSceneRuleConditionOperatorEnum.GREATER_THAN.getOperator(),
|
||||
"20"
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_PropertyNotFound() {
|
||||
// given
|
||||
Map<String, Object> properties = MapUtil.of("temperature", 25.5);
|
||||
IotDeviceMessage message = createDeviceMessage(properties);
|
||||
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
|
||||
"humidity", // 不存在的属性
|
||||
IotSceneRuleConditionOperatorEnum.GREATER_THAN.getOperator(),
|
||||
"50"
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_NullCondition() {
|
||||
// given
|
||||
Map<String, Object> properties = MapUtil.of("temperature", 25.5);
|
||||
IotDeviceMessage message = createDeviceMessage(properties);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, null);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_NullConditionType() {
|
||||
// given
|
||||
Map<String, Object> properties = MapUtil.of("temperature", 25.5);
|
||||
IotDeviceMessage message = createDeviceMessage(properties);
|
||||
IotSceneRuleDO.TriggerCondition condition = new IotSceneRuleDO.TriggerCondition();
|
||||
condition.setType(null);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_MissingIdentifier() {
|
||||
// given
|
||||
Map<String, Object> properties = MapUtil.of("temperature", 25.5);
|
||||
IotDeviceMessage message = createDeviceMessage(properties);
|
||||
IotSceneRuleDO.TriggerCondition condition = new IotSceneRuleDO.TriggerCondition();
|
||||
condition.setType(IotSceneRuleConditionTypeEnum.DEVICE_PROPERTY.getType());
|
||||
condition.setIdentifier(null); // 缺少标识符
|
||||
condition.setOperator(IotSceneRuleConditionOperatorEnum.GREATER_THAN.getOperator());
|
||||
condition.setParam("20");
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_MissingOperator() {
|
||||
// given
|
||||
Map<String, Object> properties = MapUtil.of("temperature", 25.5);
|
||||
IotDeviceMessage message = createDeviceMessage(properties);
|
||||
IotSceneRuleDO.TriggerCondition condition = new IotSceneRuleDO.TriggerCondition();
|
||||
condition.setType(IotSceneRuleConditionTypeEnum.DEVICE_PROPERTY.getType());
|
||||
condition.setIdentifier("temperature");
|
||||
condition.setOperator(null); // 缺少操作符
|
||||
condition.setParam("20");
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_MissingParam() {
|
||||
// given
|
||||
Map<String, Object> properties = MapUtil.of("temperature", 25.5);
|
||||
IotDeviceMessage message = createDeviceMessage(properties);
|
||||
IotSceneRuleDO.TriggerCondition condition = new IotSceneRuleDO.TriggerCondition();
|
||||
condition.setType(IotSceneRuleConditionTypeEnum.DEVICE_PROPERTY.getType());
|
||||
condition.setIdentifier("temperature");
|
||||
condition.setOperator(IotSceneRuleConditionOperatorEnum.GREATER_THAN.getOperator());
|
||||
condition.setParam(null); // 缺少参数
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_NullMessage() {
|
||||
// given
|
||||
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
|
||||
"temperature",
|
||||
IotSceneRuleConditionOperatorEnum.GREATER_THAN.getOperator(),
|
||||
"20"
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(null, condition);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_NullDeviceProperties() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
message.setParams(null);
|
||||
|
||||
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
|
||||
"temperature",
|
||||
IotSceneRuleConditionOperatorEnum.GREATER_THAN.getOperator(),
|
||||
"20"
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_GreaterThanOrEquals() {
|
||||
// given
|
||||
Map<String, Object> properties = MapUtil.of("voltage", 12.0);
|
||||
IotDeviceMessage message = createDeviceMessage(properties);
|
||||
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
|
||||
"voltage",
|
||||
IotSceneRuleConditionOperatorEnum.GREATER_THAN_OR_EQUALS.getOperator(),
|
||||
"12.0"
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_LessThanOrEquals() {
|
||||
// given
|
||||
Map<String, Object> properties = MapUtil.of("current", 2.5);
|
||||
IotDeviceMessage message = createDeviceMessage(properties);
|
||||
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
|
||||
"current",
|
||||
IotSceneRuleConditionOperatorEnum.LESS_THAN_OR_EQUALS.getOperator(),
|
||||
"3.0"
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_StringProperty() {
|
||||
// given
|
||||
Map<String, Object> properties = MapUtil.of("mode", "auto");
|
||||
IotDeviceMessage message = createDeviceMessage(properties);
|
||||
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
|
||||
"mode",
|
||||
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
|
||||
"auto"
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_BooleanProperty() {
|
||||
// given
|
||||
Map<String, Object> properties = MapUtil.of("enabled", true);
|
||||
IotDeviceMessage message = createDeviceMessage(properties);
|
||||
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
|
||||
"enabled",
|
||||
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
|
||||
"true"
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_MultipleProperties() {
|
||||
// given
|
||||
Map<String, Object> properties = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("temperature", 25.5)
|
||||
.put("humidity", 60)
|
||||
.put("status", "active")
|
||||
.put("enabled", true)
|
||||
.build();
|
||||
IotDeviceMessage message = createDeviceMessage(properties);
|
||||
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
|
||||
"humidity",
|
||||
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
|
||||
"60"
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
// ========== 辅助方法 ==========
|
||||
|
||||
/**
|
||||
* 创建设备消息
|
||||
*/
|
||||
private IotDeviceMessage createDeviceMessage(Map<String, Object> properties) {
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
message.setParams(properties);
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建有效的条件
|
||||
*/
|
||||
private IotSceneRuleDO.TriggerCondition createValidCondition(String identifier, String operator, String param) {
|
||||
IotSceneRuleDO.TriggerCondition condition = new IotSceneRuleDO.TriggerCondition();
|
||||
condition.setType(IotSceneRuleConditionTypeEnum.DEVICE_PROPERTY.getType());
|
||||
condition.setIdentifier(identifier);
|
||||
condition.setOperator(operator);
|
||||
condition.setParam(param);
|
||||
return condition;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,334 @@
|
||||
package cn.iocoder.yudao.module.iot.service.rule.scene.matcher.condition;
|
||||
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
|
||||
import cn.iocoder.yudao.module.iot.core.enums.IotDeviceStateEnum;
|
||||
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionOperatorEnum;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionTypeEnum;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* {@link DeviceStateConditionMatcher} 的单元测试类
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
public class DeviceStateConditionMatcherTest extends BaseMockitoUnitTest {
|
||||
|
||||
private DeviceStateConditionMatcher matcher;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
matcher = new DeviceStateConditionMatcher();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSupportedConditionType() {
|
||||
// when & then
|
||||
assertEquals(IotSceneRuleConditionTypeEnum.DEVICE_STATE, matcher.getSupportedConditionType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPriority() {
|
||||
// when & then
|
||||
assertEquals(30, matcher.getPriority());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsEnabled() {
|
||||
// when & then
|
||||
assertTrue(matcher.isEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_OnlineState() {
|
||||
// given
|
||||
IotDeviceMessage message = createDeviceMessage(IotDeviceStateEnum.ONLINE.getState());
|
||||
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
|
||||
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
|
||||
IotDeviceStateEnum.ONLINE.getState().toString()
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_OfflineState() {
|
||||
// given
|
||||
IotDeviceMessage message = createDeviceMessage(IotDeviceStateEnum.OFFLINE.getState());
|
||||
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
|
||||
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
|
||||
IotDeviceStateEnum.OFFLINE.getState().toString()
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_InactiveState() {
|
||||
// given
|
||||
IotDeviceMessage message = createDeviceMessage(IotDeviceStateEnum.INACTIVE.getState());
|
||||
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
|
||||
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
|
||||
IotDeviceStateEnum.INACTIVE.getState().toString()
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_StateMismatch() {
|
||||
// given
|
||||
IotDeviceMessage message = createDeviceMessage(IotDeviceStateEnum.ONLINE.getState());
|
||||
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
|
||||
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
|
||||
IotDeviceStateEnum.OFFLINE.getState().toString()
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_NotEqualsOperator() {
|
||||
// given
|
||||
IotDeviceMessage message = createDeviceMessage(IotDeviceStateEnum.ONLINE.getState());
|
||||
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
|
||||
IotSceneRuleConditionOperatorEnum.NOT_EQUALS.getOperator(),
|
||||
IotDeviceStateEnum.OFFLINE.getState().toString()
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_GreaterThanOperator() {
|
||||
// given
|
||||
IotDeviceMessage message = createDeviceMessage(IotDeviceStateEnum.OFFLINE.getState()); // 2
|
||||
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
|
||||
IotSceneRuleConditionOperatorEnum.GREATER_THAN.getOperator(),
|
||||
IotDeviceStateEnum.ONLINE.getState().toString() // 1
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_LessThanOperator() {
|
||||
// given
|
||||
IotDeviceMessage message = createDeviceMessage(IotDeviceStateEnum.INACTIVE.getState()); // 0
|
||||
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
|
||||
IotSceneRuleConditionOperatorEnum.LESS_THAN.getOperator(),
|
||||
IotDeviceStateEnum.ONLINE.getState().toString() // 1
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_NullCondition() {
|
||||
// given
|
||||
IotDeviceMessage message = createDeviceMessage(IotDeviceStateEnum.ONLINE.getState());
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, null);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_NullConditionType() {
|
||||
// given
|
||||
IotDeviceMessage message = createDeviceMessage(IotDeviceStateEnum.ONLINE.getState());
|
||||
IotSceneRuleDO.TriggerCondition condition = new IotSceneRuleDO.TriggerCondition();
|
||||
condition.setType(null);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_MissingOperator() {
|
||||
// given
|
||||
IotDeviceMessage message = createDeviceMessage(IotDeviceStateEnum.ONLINE.getState());
|
||||
IotSceneRuleDO.TriggerCondition condition = new IotSceneRuleDO.TriggerCondition();
|
||||
condition.setType(IotSceneRuleConditionTypeEnum.DEVICE_STATE.getType());
|
||||
condition.setOperator(null);
|
||||
condition.setParam(IotDeviceStateEnum.ONLINE.getState().toString());
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_MissingParam() {
|
||||
// given
|
||||
IotDeviceMessage message = createDeviceMessage(IotDeviceStateEnum.ONLINE.getState());
|
||||
IotSceneRuleDO.TriggerCondition condition = new IotSceneRuleDO.TriggerCondition();
|
||||
condition.setType(IotSceneRuleConditionTypeEnum.DEVICE_STATE.getType());
|
||||
condition.setOperator(IotSceneRuleConditionOperatorEnum.EQUALS.getOperator());
|
||||
condition.setParam(null);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_NullMessage() {
|
||||
// given
|
||||
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
|
||||
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
|
||||
IotDeviceStateEnum.ONLINE.getState().toString()
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(null, condition);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_NullDeviceState() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
message.setParams(null);
|
||||
|
||||
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
|
||||
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
|
||||
IotDeviceStateEnum.ONLINE.getState().toString()
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_GreaterThanOrEqualsOperator() {
|
||||
// given
|
||||
IotDeviceMessage message = createDeviceMessage(IotDeviceStateEnum.ONLINE.getState()); // 1
|
||||
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
|
||||
IotSceneRuleConditionOperatorEnum.GREATER_THAN_OR_EQUALS.getOperator(),
|
||||
IotDeviceStateEnum.ONLINE.getState().toString() // 1
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_LessThanOrEqualsOperator() {
|
||||
// given
|
||||
IotDeviceMessage message = createDeviceMessage(IotDeviceStateEnum.ONLINE.getState()); // 1
|
||||
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
|
||||
IotSceneRuleConditionOperatorEnum.LESS_THAN_OR_EQUALS.getOperator(),
|
||||
IotDeviceStateEnum.OFFLINE.getState().toString() // 2
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_InvalidOperator() {
|
||||
// given
|
||||
IotDeviceMessage message = createDeviceMessage(IotDeviceStateEnum.ONLINE.getState());
|
||||
IotSceneRuleDO.TriggerCondition condition = new IotSceneRuleDO.TriggerCondition();
|
||||
condition.setType(IotSceneRuleConditionTypeEnum.DEVICE_STATE.getType());
|
||||
condition.setOperator("invalid_operator");
|
||||
condition.setParam(IotDeviceStateEnum.ONLINE.getState().toString());
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_InvalidParamFormat() {
|
||||
// given
|
||||
IotDeviceMessage message = createDeviceMessage(IotDeviceStateEnum.ONLINE.getState());
|
||||
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
|
||||
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
|
||||
"invalid_state_value"
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, condition);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
// ========== 辅助方法 ==========
|
||||
|
||||
/**
|
||||
* 创建设备消息
|
||||
*/
|
||||
private IotDeviceMessage createDeviceMessage(Integer deviceState) {
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
message.setParams(deviceState);
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建有效的条件
|
||||
*/
|
||||
private IotSceneRuleDO.TriggerCondition createValidCondition(String operator, String param) {
|
||||
IotSceneRuleDO.TriggerCondition condition = new IotSceneRuleDO.TriggerCondition();
|
||||
condition.setType(IotSceneRuleConditionTypeEnum.DEVICE_STATE.getType());
|
||||
condition.setOperator(operator);
|
||||
condition.setParam(param);
|
||||
return condition;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,341 @@
|
||||
package cn.iocoder.yudao.module.iot.service.rule.scene.matcher.trigger;
|
||||
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
|
||||
import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageMethodEnum;
|
||||
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* {@link DeviceEventPostTriggerMatcher} 的单元测试类
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
public class DeviceEventPostTriggerMatcherTest extends BaseMockitoUnitTest {
|
||||
|
||||
private DeviceEventPostTriggerMatcher matcher;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
matcher = new DeviceEventPostTriggerMatcher();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSupportedTriggerType() {
|
||||
// when & then
|
||||
assertEquals(IotSceneRuleTriggerTypeEnum.DEVICE_EVENT_POST, matcher.getSupportedTriggerType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPriority() {
|
||||
// when & then
|
||||
assertEquals(30, matcher.getPriority());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsEnabled() {
|
||||
// when & then
|
||||
assertTrue(matcher.isEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_AlarmEvent() {
|
||||
// given
|
||||
Map<String, Object> eventParams = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("identifier", "alarm")
|
||||
.put("value", MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("level", "high")
|
||||
.put("message", "Temperature too high")
|
||||
.build())
|
||||
.build();
|
||||
IotDeviceMessage message = createEventPostMessage(eventParams);
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger("alarm");
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_ErrorEvent() {
|
||||
// given
|
||||
Map<String, Object> eventParams = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("identifier", "error")
|
||||
.put("value", MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("code", 500)
|
||||
.put("description", "System error")
|
||||
.build())
|
||||
.build();
|
||||
IotDeviceMessage message = createEventPostMessage(eventParams);
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger("error");
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_InfoEvent() {
|
||||
// given
|
||||
Map<String, Object> eventParams = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("identifier", "info")
|
||||
.put("value", MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("status", "normal")
|
||||
.put("timestamp", System.currentTimeMillis())
|
||||
.build())
|
||||
.build();
|
||||
IotDeviceMessage message = createEventPostMessage(eventParams);
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger("info");
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_EventIdentifierMismatch() {
|
||||
// given
|
||||
Map<String, Object> eventParams = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("identifier", "alarm")
|
||||
.put("value", MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("level", "high")
|
||||
.build())
|
||||
.build();
|
||||
IotDeviceMessage message = createEventPostMessage(eventParams);
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger("error"); // 不匹配的事件标识符
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_WrongMessageMethod() {
|
||||
// given
|
||||
Map<String, Object> eventParams = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("identifier", "alarm")
|
||||
.put("value", MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("level", "high")
|
||||
.build())
|
||||
.build();
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
message.setMethod(IotDeviceMessageMethodEnum.PROPERTY_POST.getMethod()); // 错误的方法
|
||||
message.setParams(eventParams);
|
||||
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger("alarm");
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_MissingIdentifier() {
|
||||
// given
|
||||
Map<String, Object> eventParams = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("identifier", "alarm")
|
||||
.put("value", MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("level", "high")
|
||||
.build())
|
||||
.build();
|
||||
IotDeviceMessage message = createEventPostMessage(eventParams);
|
||||
IotSceneRuleDO.Trigger trigger = new IotSceneRuleDO.Trigger();
|
||||
trigger.setType(IotSceneRuleTriggerTypeEnum.DEVICE_EVENT_POST.getType());
|
||||
trigger.setIdentifier(null); // 缺少标识符
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_NullMessageParams() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
message.setMethod(IotDeviceMessageMethodEnum.EVENT_POST.getMethod());
|
||||
message.setParams(null);
|
||||
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger("alarm");
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_InvalidMessageParams() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
message.setMethod(IotDeviceMessageMethodEnum.EVENT_POST.getMethod());
|
||||
message.setParams("invalid-params"); // 不是 Map 类型
|
||||
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger("alarm");
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_MissingEventIdentifierInParams() {
|
||||
// given
|
||||
Map<String, Object> eventParams = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("value", MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("level", "high")
|
||||
.build()) // 缺少 identifier 字段
|
||||
.build();
|
||||
IotDeviceMessage message = createEventPostMessage(eventParams);
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger("alarm");
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_NullTrigger() {
|
||||
// given
|
||||
Map<String, Object> eventParams = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("identifier", "alarm")
|
||||
.put("value", MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("level", "high")
|
||||
.build())
|
||||
.build();
|
||||
IotDeviceMessage message = createEventPostMessage(eventParams);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, null);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_NullTriggerType() {
|
||||
// given
|
||||
Map<String, Object> eventParams = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("identifier", "alarm")
|
||||
.put("value", MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("level", "high")
|
||||
.build())
|
||||
.build();
|
||||
IotDeviceMessage message = createEventPostMessage(eventParams);
|
||||
IotSceneRuleDO.Trigger trigger = new IotSceneRuleDO.Trigger();
|
||||
trigger.setType(null);
|
||||
trigger.setIdentifier("alarm");
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_ComplexEventValue() {
|
||||
// given
|
||||
Map<String, Object> eventParams = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("identifier", "maintenance")
|
||||
.put("value", MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("type", "scheduled")
|
||||
.put("duration", 120)
|
||||
.put("components", new String[]{"motor", "sensor"})
|
||||
.put("priority", "medium")
|
||||
.build())
|
||||
.build();
|
||||
IotDeviceMessage message = createEventPostMessage(eventParams);
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger("maintenance");
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_EmptyEventValue() {
|
||||
// given
|
||||
Map<String, Object> eventParams = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("identifier", "heartbeat")
|
||||
.put("value", MapUtil.of()) // 空的事件值
|
||||
.build();
|
||||
IotDeviceMessage message = createEventPostMessage(eventParams);
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger("heartbeat");
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_CaseInsensitiveIdentifier() {
|
||||
// given
|
||||
Map<String, Object> eventParams = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("identifier", "ALARM") // 大写
|
||||
.put("value", MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("level", "high")
|
||||
.build())
|
||||
.build();
|
||||
IotDeviceMessage message = createEventPostMessage(eventParams);
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger("alarm"); // 小写
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
// 根据实际实现,这里可能需要调整期望结果
|
||||
// 如果实现是大小写敏感的,则应该为 false
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
// ========== 辅助方法 ==========
|
||||
|
||||
/**
|
||||
* 创建事件上报消息
|
||||
*/
|
||||
private IotDeviceMessage createEventPostMessage(Map<String, Object> eventParams) {
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
message.setMethod(IotDeviceMessageMethodEnum.EVENT_POST.getMethod());
|
||||
message.setParams(eventParams);
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建有效的触发器
|
||||
*/
|
||||
private IotSceneRuleDO.Trigger createValidTrigger(String identifier) {
|
||||
IotSceneRuleDO.Trigger trigger = new IotSceneRuleDO.Trigger();
|
||||
trigger.setType(IotSceneRuleTriggerTypeEnum.DEVICE_EVENT_POST.getType());
|
||||
trigger.setIdentifier(identifier);
|
||||
return trigger;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,298 @@
|
||||
package cn.iocoder.yudao.module.iot.service.rule.scene.matcher.trigger;
|
||||
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
|
||||
import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageMethodEnum;
|
||||
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionOperatorEnum;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* {@link DevicePropertyPostTriggerMatcher} 的单元测试类
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
public class DevicePropertyPostTriggerMatcherTest extends BaseMockitoUnitTest {
|
||||
|
||||
private DevicePropertyPostTriggerMatcher matcher;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
matcher = new DevicePropertyPostTriggerMatcher();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSupportedTriggerType() {
|
||||
// when & then
|
||||
assertEquals(IotSceneRuleTriggerTypeEnum.DEVICE_PROPERTY_POST, matcher.getSupportedTriggerType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPriority() {
|
||||
// when & then
|
||||
assertEquals(20, matcher.getPriority());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsEnabled() {
|
||||
// when & then
|
||||
assertTrue(matcher.isEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_TemperatureProperty() {
|
||||
// given
|
||||
Map<String, Object> properties = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("temperature", 25.5)
|
||||
.build();
|
||||
IotDeviceMessage message = createPropertyPostMessage(properties);
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger(
|
||||
"temperature",
|
||||
IotSceneRuleConditionOperatorEnum.GREATER_THAN.getOperator(),
|
||||
"20"
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_HumidityProperty() {
|
||||
// given
|
||||
Map<String, Object> properties = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("humidity", 60)
|
||||
.build();
|
||||
IotDeviceMessage message = createPropertyPostMessage(properties);
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger(
|
||||
"humidity",
|
||||
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
|
||||
"60"
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_PropertyMismatch() {
|
||||
// given
|
||||
Map<String, Object> properties = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("temperature", 15.0)
|
||||
.build();
|
||||
IotDeviceMessage message = createPropertyPostMessage(properties);
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger(
|
||||
"temperature",
|
||||
IotSceneRuleConditionOperatorEnum.GREATER_THAN.getOperator(),
|
||||
"20"
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_PropertyNotFound() {
|
||||
// given
|
||||
Map<String, Object> properties = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("temperature", 25.5)
|
||||
.build();
|
||||
IotDeviceMessage message = createPropertyPostMessage(properties);
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger(
|
||||
"humidity", // 不存在的属性
|
||||
IotSceneRuleConditionOperatorEnum.GREATER_THAN.getOperator(),
|
||||
"50"
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_WrongMessageMethod() {
|
||||
// given
|
||||
Map<String, Object> properties = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("temperature", 25.5)
|
||||
.build();
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
message.setMethod(IotDeviceMessageMethodEnum.STATE_UPDATE.getMethod());
|
||||
message.setParams(properties);
|
||||
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger(
|
||||
"temperature",
|
||||
IotSceneRuleConditionOperatorEnum.GREATER_THAN.getOperator(),
|
||||
"20"
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_MissingIdentifier() {
|
||||
// given
|
||||
Map<String, Object> properties = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("temperature", 25.5)
|
||||
.build();
|
||||
IotDeviceMessage message = createPropertyPostMessage(properties);
|
||||
IotSceneRuleDO.Trigger trigger = new IotSceneRuleDO.Trigger();
|
||||
trigger.setType(IotSceneRuleTriggerTypeEnum.DEVICE_PROPERTY_POST.getType());
|
||||
trigger.setIdentifier(null); // 缺少标识符
|
||||
trigger.setOperator(IotSceneRuleConditionOperatorEnum.GREATER_THAN.getOperator());
|
||||
trigger.setValue("20");
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_NullMessageParams() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
message.setMethod(IotDeviceMessageMethodEnum.PROPERTY_POST.getMethod());
|
||||
message.setParams(null);
|
||||
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger(
|
||||
"temperature",
|
||||
IotSceneRuleConditionOperatorEnum.GREATER_THAN.getOperator(),
|
||||
"20"
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_InvalidMessageParams() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
message.setMethod(IotDeviceMessageMethodEnum.PROPERTY_POST.getMethod());
|
||||
message.setParams("invalid-params"); // 不是 Map 类型
|
||||
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger(
|
||||
"temperature",
|
||||
IotSceneRuleConditionOperatorEnum.GREATER_THAN.getOperator(),
|
||||
"20"
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_LessThanOperator() {
|
||||
// given
|
||||
Map<String, Object> properties = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("temperature", 15.0)
|
||||
.build();
|
||||
IotDeviceMessage message = createPropertyPostMessage(properties);
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger(
|
||||
"temperature",
|
||||
IotSceneRuleConditionOperatorEnum.LESS_THAN.getOperator(),
|
||||
"20"
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_NotEqualsOperator() {
|
||||
// given
|
||||
Map<String, Object> properties = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("status", "active")
|
||||
.build();
|
||||
IotDeviceMessage message = createPropertyPostMessage(properties);
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger(
|
||||
"status",
|
||||
IotSceneRuleConditionOperatorEnum.NOT_EQUALS.getOperator(),
|
||||
"inactive"
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_MultipleProperties() {
|
||||
// given
|
||||
Map<String, Object> properties = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("temperature", 25.5)
|
||||
.put("humidity", 60)
|
||||
.put("status", "active")
|
||||
.build();
|
||||
IotDeviceMessage message = createPropertyPostMessage(properties);
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger(
|
||||
"humidity",
|
||||
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
|
||||
"60"
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
// ========== 辅助方法 ==========
|
||||
|
||||
/**
|
||||
* 创建属性上报消息
|
||||
*/
|
||||
private IotDeviceMessage createPropertyPostMessage(Map<String, Object> properties) {
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
message.setMethod(IotDeviceMessageMethodEnum.PROPERTY_POST.getMethod());
|
||||
message.setParams(properties);
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建有效的触发器
|
||||
*/
|
||||
private IotSceneRuleDO.Trigger createValidTrigger(String identifier, String operator, String value) {
|
||||
IotSceneRuleDO.Trigger trigger = new IotSceneRuleDO.Trigger();
|
||||
trigger.setType(IotSceneRuleTriggerTypeEnum.DEVICE_PROPERTY_POST.getType());
|
||||
trigger.setIdentifier(identifier);
|
||||
trigger.setOperator(operator);
|
||||
trigger.setValue(value);
|
||||
return trigger;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,362 @@
|
||||
package cn.iocoder.yudao.module.iot.service.rule.scene.matcher.trigger;
|
||||
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
|
||||
import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageMethodEnum;
|
||||
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* {@link DeviceServiceInvokeTriggerMatcher} 的单元测试类
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
public class DeviceServiceInvokeTriggerMatcherTest extends BaseMockitoUnitTest {
|
||||
|
||||
private DeviceServiceInvokeTriggerMatcher matcher;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
matcher = new DeviceServiceInvokeTriggerMatcher();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSupportedTriggerType() {
|
||||
// when & then
|
||||
assertEquals(IotSceneRuleTriggerTypeEnum.DEVICE_SERVICE_INVOKE, matcher.getSupportedTriggerType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPriority() {
|
||||
// when & then
|
||||
assertEquals(40, matcher.getPriority());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsEnabled() {
|
||||
// when & then
|
||||
assertTrue(matcher.isEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_RestartService() {
|
||||
// given
|
||||
Map<String, Object> serviceParams = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("identifier", "restart")
|
||||
.put("inputData", MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("mode", "soft")
|
||||
.build())
|
||||
.build();
|
||||
IotDeviceMessage message = createServiceInvokeMessage(serviceParams);
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger("restart");
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_ConfigService() {
|
||||
// given
|
||||
Map<String, Object> serviceParams = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("identifier", "config")
|
||||
.put("inputData", MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("interval", 30)
|
||||
.put("enabled", true)
|
||||
.put("threshold", 75.5)
|
||||
.build())
|
||||
.build();
|
||||
IotDeviceMessage message = createServiceInvokeMessage(serviceParams);
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger("config");
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_UpdateService() {
|
||||
// given
|
||||
Map<String, Object> serviceParams = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("identifier", "update")
|
||||
.put("inputData", MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("version", "1.2.3")
|
||||
.put("url", "http://example.com/firmware.bin")
|
||||
.build())
|
||||
.build();
|
||||
IotDeviceMessage message = createServiceInvokeMessage(serviceParams);
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger("update");
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_ServiceIdentifierMismatch() {
|
||||
// given
|
||||
Map<String, Object> serviceParams = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("identifier", "restart")
|
||||
.put("inputData", MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("mode", "soft")
|
||||
.build())
|
||||
.build();
|
||||
IotDeviceMessage message = createServiceInvokeMessage(serviceParams);
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger("config"); // 不匹配的服务标识符
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_WrongMessageMethod() {
|
||||
// given
|
||||
Map<String, Object> serviceParams = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("identifier", "restart")
|
||||
.put("inputData", MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("mode", "soft")
|
||||
.build())
|
||||
.build();
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
message.setMethod(IotDeviceMessageMethodEnum.PROPERTY_POST.getMethod()); // 错误的方法
|
||||
message.setParams(serviceParams);
|
||||
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger("restart");
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_MissingIdentifier() {
|
||||
// given
|
||||
Map<String, Object> serviceParams = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("identifier", "restart")
|
||||
.put("inputData", MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("mode", "soft")
|
||||
.build())
|
||||
.build();
|
||||
IotDeviceMessage message = createServiceInvokeMessage(serviceParams);
|
||||
IotSceneRuleDO.Trigger trigger = new IotSceneRuleDO.Trigger();
|
||||
trigger.setType(IotSceneRuleTriggerTypeEnum.DEVICE_SERVICE_INVOKE.getType());
|
||||
trigger.setIdentifier(null); // 缺少标识符
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_NullMessageParams() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
message.setMethod(IotDeviceMessageMethodEnum.SERVICE_INVOKE.getMethod());
|
||||
message.setParams(null);
|
||||
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger("restart");
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_InvalidMessageParams() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
message.setMethod(IotDeviceMessageMethodEnum.SERVICE_INVOKE.getMethod());
|
||||
message.setParams("invalid-params"); // 不是 Map 类型
|
||||
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger("restart");
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_MissingServiceIdentifierInParams() {
|
||||
// given
|
||||
Map<String, Object> serviceParams = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("inputData", MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("mode", "soft")
|
||||
.build()) // 缺少 identifier 字段
|
||||
.build();
|
||||
IotDeviceMessage message = createServiceInvokeMessage(serviceParams);
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger("restart");
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_NullTrigger() {
|
||||
// given
|
||||
Map<String, Object> serviceParams = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("identifier", "restart")
|
||||
.put("inputData", MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("mode", "soft")
|
||||
.build())
|
||||
.build();
|
||||
IotDeviceMessage message = createServiceInvokeMessage(serviceParams);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, null);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_NullTriggerType() {
|
||||
// given
|
||||
Map<String, Object> serviceParams = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("identifier", "restart")
|
||||
.put("inputData", MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("mode", "soft")
|
||||
.build())
|
||||
.build();
|
||||
IotDeviceMessage message = createServiceInvokeMessage(serviceParams);
|
||||
IotSceneRuleDO.Trigger trigger = new IotSceneRuleDO.Trigger();
|
||||
trigger.setType(null);
|
||||
trigger.setIdentifier("restart");
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_EmptyInputData() {
|
||||
// given
|
||||
Map<String, Object> serviceParams = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("identifier", "ping")
|
||||
.put("inputData", MapUtil.of()) // 空的输入数据
|
||||
.build();
|
||||
IotDeviceMessage message = createServiceInvokeMessage(serviceParams);
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger("ping");
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_NoInputData() {
|
||||
// given
|
||||
Map<String, Object> serviceParams = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("identifier", "status")
|
||||
// 没有 inputData 字段
|
||||
.build();
|
||||
IotDeviceMessage message = createServiceInvokeMessage(serviceParams);
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger("status");
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_ComplexInputData() {
|
||||
// given
|
||||
Map<String, Object> serviceParams = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("identifier", "calibrate")
|
||||
.put("inputData", MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("sensors", new String[]{"temperature", "humidity", "pressure"})
|
||||
.put("precision", 0.01)
|
||||
.put("duration", 300)
|
||||
.put("autoSave", true)
|
||||
.put("config", MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("mode", "auto")
|
||||
.put("level", "high")
|
||||
.build())
|
||||
.build())
|
||||
.build();
|
||||
IotDeviceMessage message = createServiceInvokeMessage(serviceParams);
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger("calibrate");
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_CaseInsensitiveIdentifier() {
|
||||
// given
|
||||
Map<String, Object> serviceParams = MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("identifier", "RESTART") // 大写
|
||||
.put("inputData", MapUtil.builder(new HashMap<String, Object>())
|
||||
.put("mode", "soft")
|
||||
.build())
|
||||
.build();
|
||||
IotDeviceMessage message = createServiceInvokeMessage(serviceParams);
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger("restart"); // 小写
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
// 根据实际实现,这里可能需要调整期望结果
|
||||
// 如果实现是大小写敏感的,则应该为 false
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
// ========== 辅助方法 ==========
|
||||
|
||||
/**
|
||||
* 创建服务调用消息
|
||||
*/
|
||||
private IotDeviceMessage createServiceInvokeMessage(Map<String, Object> serviceParams) {
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
message.setMethod(IotDeviceMessageMethodEnum.SERVICE_INVOKE.getMethod());
|
||||
message.setParams(serviceParams);
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建有效的触发器
|
||||
*/
|
||||
private IotSceneRuleDO.Trigger createValidTrigger(String identifier) {
|
||||
IotSceneRuleDO.Trigger trigger = new IotSceneRuleDO.Trigger();
|
||||
trigger.setType(IotSceneRuleTriggerTypeEnum.DEVICE_SERVICE_INVOKE.getType());
|
||||
trigger.setIdentifier(identifier);
|
||||
return trigger;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,245 @@
|
||||
package cn.iocoder.yudao.module.iot.service.rule.scene.matcher.trigger;
|
||||
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
|
||||
import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageMethodEnum;
|
||||
import cn.iocoder.yudao.module.iot.core.enums.IotDeviceStateEnum;
|
||||
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionOperatorEnum;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* {@link DeviceStateUpdateTriggerMatcher} 的单元测试类
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
public class DeviceStateUpdateTriggerMatcherTest extends BaseMockitoUnitTest {
|
||||
|
||||
private DeviceStateUpdateTriggerMatcher matcher;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
matcher = new DeviceStateUpdateTriggerMatcher();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSupportedTriggerType() {
|
||||
// when & then
|
||||
assertEquals(IotSceneRuleTriggerTypeEnum.DEVICE_STATE_UPDATE, matcher.getSupportedTriggerType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPriority() {
|
||||
// when & then
|
||||
assertEquals(10, matcher.getPriority());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsEnabled() {
|
||||
// when & then
|
||||
assertTrue(matcher.isEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_OnlineState() {
|
||||
// given
|
||||
IotDeviceMessage message = createStateUpdateMessage(IotDeviceStateEnum.ONLINE.getState());
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger(
|
||||
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
|
||||
IotDeviceStateEnum.ONLINE.getState().toString()
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_OfflineState() {
|
||||
// given
|
||||
IotDeviceMessage message = createStateUpdateMessage(IotDeviceStateEnum.OFFLINE.getState());
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger(
|
||||
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
|
||||
IotDeviceStateEnum.OFFLINE.getState().toString()
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_StateMismatch() {
|
||||
// given
|
||||
IotDeviceMessage message = createStateUpdateMessage(IotDeviceStateEnum.ONLINE.getState());
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger(
|
||||
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
|
||||
IotDeviceStateEnum.OFFLINE.getState().toString()
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_NullTrigger() {
|
||||
// given
|
||||
IotDeviceMessage message = createStateUpdateMessage(IotDeviceStateEnum.ONLINE.getState());
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, null);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_NullTriggerType() {
|
||||
// given
|
||||
IotDeviceMessage message = createStateUpdateMessage(IotDeviceStateEnum.ONLINE.getState());
|
||||
IotSceneRuleDO.Trigger trigger = new IotSceneRuleDO.Trigger();
|
||||
trigger.setType(null);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_WrongMessageMethod() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
message.setMethod(IotDeviceMessageMethodEnum.PROPERTY_POST.getMethod());
|
||||
message.setParams(IotDeviceStateEnum.ONLINE.getState());
|
||||
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger(
|
||||
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
|
||||
IotDeviceStateEnum.ONLINE.getState().toString()
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_MissingOperator() {
|
||||
// given
|
||||
IotDeviceMessage message = createStateUpdateMessage(IotDeviceStateEnum.ONLINE.getState());
|
||||
IotSceneRuleDO.Trigger trigger = new IotSceneRuleDO.Trigger();
|
||||
trigger.setType(IotSceneRuleTriggerTypeEnum.DEVICE_STATE_UPDATE.getType());
|
||||
trigger.setOperator(null);
|
||||
trigger.setValue(IotDeviceStateEnum.ONLINE.getState().toString());
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_MissingValue() {
|
||||
// given
|
||||
IotDeviceMessage message = createStateUpdateMessage(IotDeviceStateEnum.ONLINE.getState());
|
||||
IotSceneRuleDO.Trigger trigger = new IotSceneRuleDO.Trigger();
|
||||
trigger.setType(IotSceneRuleTriggerTypeEnum.DEVICE_STATE_UPDATE.getType());
|
||||
trigger.setOperator(IotSceneRuleConditionOperatorEnum.EQUALS.getOperator());
|
||||
trigger.setValue(null);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_NullMessageParams() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
message.setMethod(IotDeviceMessageMethodEnum.STATE_UPDATE.getMethod());
|
||||
message.setParams(null);
|
||||
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger(
|
||||
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
|
||||
IotDeviceStateEnum.ONLINE.getState().toString()
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_GreaterThanOperator() {
|
||||
// given
|
||||
IotDeviceMessage message = createStateUpdateMessage(IotDeviceStateEnum.ONLINE.getState());
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger(
|
||||
IotSceneRuleConditionOperatorEnum.GREATER_THAN.getOperator(),
|
||||
IotDeviceStateEnum.INACTIVE.getState().toString()
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_NotEqualsOperator() {
|
||||
// given
|
||||
IotDeviceMessage message = createStateUpdateMessage(IotDeviceStateEnum.ONLINE.getState());
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger(
|
||||
IotSceneRuleConditionOperatorEnum.NOT_EQUALS.getOperator(),
|
||||
IotDeviceStateEnum.OFFLINE.getState().toString()
|
||||
);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
// ========== 辅助方法 ==========
|
||||
|
||||
/**
|
||||
* 创建设备状态更新消息
|
||||
*/
|
||||
private IotDeviceMessage createStateUpdateMessage(Integer state) {
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
message.setMethod(IotDeviceMessageMethodEnum.STATE_UPDATE.getMethod());
|
||||
message.setParams(state);
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建有效的触发器
|
||||
*/
|
||||
private IotSceneRuleDO.Trigger createValidTrigger(String operator, String value) {
|
||||
IotSceneRuleDO.Trigger trigger = new IotSceneRuleDO.Trigger();
|
||||
trigger.setType(IotSceneRuleTriggerTypeEnum.DEVICE_STATE_UPDATE.getType());
|
||||
trigger.setOperator(operator);
|
||||
trigger.setValue(value);
|
||||
return trigger;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,240 @@
|
||||
package cn.iocoder.yudao.module.iot.service.rule.scene.matcher.trigger;
|
||||
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
|
||||
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* {@link TimerTriggerMatcher} 的单元测试类
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
public class TimerTriggerMatcherTest extends BaseMockitoUnitTest {
|
||||
|
||||
private TimerTriggerMatcher matcher;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
matcher = new TimerTriggerMatcher();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSupportedTriggerType() {
|
||||
// when & then
|
||||
assertEquals(IotSceneRuleTriggerTypeEnum.TIMER, matcher.getSupportedTriggerType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPriority() {
|
||||
// when & then
|
||||
assertEquals(50, matcher.getPriority());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsEnabled() {
|
||||
// when & then
|
||||
assertTrue(matcher.isEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_ValidCronExpression() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger("0 0 12 * * ?"); // 每天中午12点
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_EveryMinuteCron() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger("0 * * * * ?"); // 每分钟
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_WeekdaysCron() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger("0 0 9 ? * MON-FRI"); // 工作日上午9点
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_InvalidCronExpression() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger("invalid-cron-expression");
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_EmptyCronExpression() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger("");
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_NullCronExpression() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
IotSceneRuleDO.Trigger trigger = new IotSceneRuleDO.Trigger();
|
||||
trigger.setType(IotSceneRuleTriggerTypeEnum.TIMER.getType());
|
||||
trigger.setCronExpression(null);
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_NullTrigger() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, null);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_NullTriggerType() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
IotSceneRuleDO.Trigger trigger = new IotSceneRuleDO.Trigger();
|
||||
trigger.setType(null);
|
||||
trigger.setCronExpression("0 0 12 * * ?");
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_ComplexCronExpression() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger("0 15 10 ? * 6#3"); // 每月第三个星期五上午10:15
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_IncorrectCronFormat() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger("0 0 12 * *"); // 缺少字段
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_SpecificDateCron() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger("0 0 0 1 1 ? 2025"); // 2025年1月1日午夜
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_EverySecondCron() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger("* * * * * ?"); // 每秒
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Failure_InvalidCharactersCron() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger("0 0 12 * * @ #"); // 包含无效字符
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsMatched_Success_RangeCron() {
|
||||
// given
|
||||
IotDeviceMessage message = new IotDeviceMessage();
|
||||
IotSceneRuleDO.Trigger trigger = createValidTrigger("0 0 9-17 * * MON-FRI"); // 工作日9-17点
|
||||
|
||||
// when
|
||||
boolean result = matcher.isMatched(message, trigger);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
// ========== 辅助方法 ==========
|
||||
|
||||
/**
|
||||
* 创建有效的定时触发器
|
||||
*/
|
||||
private IotSceneRuleDO.Trigger createValidTrigger(String cronExpression) {
|
||||
IotSceneRuleDO.Trigger trigger = new IotSceneRuleDO.Trigger();
|
||||
trigger.setType(IotSceneRuleTriggerTypeEnum.TIMER.getType());
|
||||
trigger.setCronExpression(cronExpression);
|
||||
return trigger;
|
||||
}
|
||||
}
|
||||
@ -20,6 +20,15 @@ mybatis-plus:
|
||||
lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试
|
||||
type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject
|
||||
|
||||
# 日志配置
|
||||
logging:
|
||||
level:
|
||||
cn.iocoder.yudao.module.iot.service.rule.scene.matcher: DEBUG
|
||||
cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcherManager: INFO
|
||||
cn.iocoder.yudao.module.iot.service.rule.scene.matcher.condition: DEBUG
|
||||
cn.iocoder.yudao.module.iot.service.rule.scene.matcher.trigger: DEBUG
|
||||
root: WARN
|
||||
|
||||
--- #################### 定时任务相关配置 ####################
|
||||
|
||||
--- #################### 配置中心相关配置 ####################
|
||||
|
||||
@ -1,4 +1,37 @@
|
||||
<configuration>
|
||||
<!-- 引用 Spring Boot 的 logback 基础配置 -->
|
||||
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
|
||||
|
||||
<!-- 控制台输出 -->
|
||||
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 设置特定包的日志级别 -->
|
||||
<logger name="cn.iocoder.yudao.module.iot.service.rule.scene.matcher" level="DEBUG" additivity="false">
|
||||
<appender-ref ref="CONSOLE"/>
|
||||
</logger>
|
||||
|
||||
<!-- 设置 IotSceneRuleMatcherManager 的日志级别 -->
|
||||
<logger name="cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcherManager" level="INFO"
|
||||
additivity="false">
|
||||
<appender-ref ref="CONSOLE"/>
|
||||
</logger>
|
||||
|
||||
<!-- 设置所有匹配器的日志级别 -->
|
||||
<logger name="cn.iocoder.yudao.module.iot.service.rule.scene.matcher.condition" level="DEBUG" additivity="false">
|
||||
<appender-ref ref="CONSOLE"/>
|
||||
</logger>
|
||||
|
||||
<logger name="cn.iocoder.yudao.module.iot.service.rule.scene.matcher.trigger" level="DEBUG" additivity="false">
|
||||
<appender-ref ref="CONSOLE"/>
|
||||
</logger>
|
||||
|
||||
<!-- 根日志级别 -->
|
||||
<root level="WARN">
|
||||
<appender-ref ref="CONSOLE"/>
|
||||
</root>
|
||||
</configuration>
|
||||
|
||||
@ -185,6 +185,7 @@ logging:
|
||||
cn.iocoder.yudao.module.erp.dal.mysql: debug
|
||||
cn.iocoder.yudao.module.iot.dal.mysql: debug
|
||||
cn.iocoder.yudao.module.iot.dal.tdengine: DEBUG
|
||||
cn.iocoder.yudao.module.iot.service.rule: debug
|
||||
cn.iocoder.yudao.module.ai.dal.mysql: debug
|
||||
org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR # TODO 芋艿:先禁用,Spring Boot 3.X 存在部分错误的 WARN 提示
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user