소스 검색

perf:【iot】添加 IotDeviceMessageUtils.notContainsIdentifier 方法

puhui999 8 달 전
부모
커밋
5bc8a4e487

+ 1 - 2
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/trigger/IotDevicePropertyPostTriggerMatcher.java

@@ -38,8 +38,7 @@ public class IotDevicePropertyPostTriggerMatcher implements IotSceneRuleTriggerM
 
         // 1.3 检查消息中是否包含触发器指定的属性标识符
         // 注意:属性上报可能同时上报多个属性,所以需要判断 trigger.getIdentifier() 是否在 message 的 params 中
-        // TODO @puhui999:可以考虑 notXXX 方法,简化代码(尽量取反)
-        if (!IotDeviceMessageUtils.containsIdentifier(message, trigger.getIdentifier())) {
+        if (IotDeviceMessageUtils.notContainsIdentifier(message, trigger.getIdentifier())) {
             IotSceneRuleMatcherHelper.logTriggerMatchFailure(message, trigger, "消息中不包含属性: " +
                     trigger.getIdentifier());
             return false;

+ 151 - 0
yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/rule/data/action/tcp/IotTcpClientTest.java

@@ -0,0 +1,151 @@
+package cn.iocoder.yudao.module.iot.service.rule.data.action.tcp;
+
+import cn.hutool.core.util.ReflectUtil;
+import cn.iocoder.yudao.module.iot.dal.dataobject.rule.config.IotDataSinkTcpConfig;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * {@link IotTcpClient} 的单元测试
+ * <p>
+ * 测试 dataFormat 默认值行为
+ * Property 1: TCP 客户端 dataFormat 默认值行为
+ * Validates: Requirements 1.1, 1.2
+ *
+ * @author HUIHUI
+ */
+class IotTcpClientTest {
+
+    @Test
+    public void testConstructor_dataFormatNull() {
+        // 准备参数
+        String host = "localhost";
+        Integer port = 8080;
+
+        // 调用
+        IotTcpClient client = new IotTcpClient(host, port, null, null, null, null);
+
+        // 断言:dataFormat 为 null 时应使用默认值
+        assertEquals(IotDataSinkTcpConfig.DEFAULT_DATA_FORMAT,
+                ReflectUtil.getFieldValue(client, "dataFormat"));
+    }
+
+    @Test
+    public void testConstructor_dataFormatEmpty() {
+        // 准备参数
+        String host = "localhost";
+        Integer port = 8080;
+
+        // 调用
+        IotTcpClient client = new IotTcpClient(host, port, null, null, null, "");
+
+        // 断言:dataFormat 为空字符串时应使用默认值
+        assertEquals(IotDataSinkTcpConfig.DEFAULT_DATA_FORMAT,
+                ReflectUtil.getFieldValue(client, "dataFormat"));
+    }
+
+    @Test
+    public void testConstructor_dataFormatBlank() {
+        // 准备参数
+        String host = "localhost";
+        Integer port = 8080;
+
+        // 调用
+        IotTcpClient client = new IotTcpClient(host, port, null, null, null, "   ");
+
+        // 断言:dataFormat 为纯空白字符串时应使用默认值
+        assertEquals(IotDataSinkTcpConfig.DEFAULT_DATA_FORMAT,
+                ReflectUtil.getFieldValue(client, "dataFormat"));
+    }
+
+    @Test
+    public void testConstructor_dataFormatValid() {
+        // 准备参数
+        String host = "localhost";
+        Integer port = 8080;
+        String dataFormat = "BINARY";
+
+        // 调用
+        IotTcpClient client = new IotTcpClient(host, port, null, null, null, dataFormat);
+
+        // 断言:dataFormat 为有效值时应保持原值
+        assertEquals(dataFormat, ReflectUtil.getFieldValue(client, "dataFormat"));
+    }
+
+    @Test
+    public void testConstructor_defaultValues() {
+        // 准备参数
+        String host = "localhost";
+        Integer port = 8080;
+
+        // 调用
+        IotTcpClient client = new IotTcpClient(host, port, null, null, null, null);
+
+        // 断言:验证所有默认值
+        assertEquals(host, ReflectUtil.getFieldValue(client, "host"));
+        assertEquals(port, ReflectUtil.getFieldValue(client, "port"));
+        assertEquals(IotDataSinkTcpConfig.DEFAULT_CONNECT_TIMEOUT_MS,
+                ReflectUtil.getFieldValue(client, "connectTimeoutMs"));
+        assertEquals(IotDataSinkTcpConfig.DEFAULT_READ_TIMEOUT_MS,
+                ReflectUtil.getFieldValue(client, "readTimeoutMs"));
+        assertEquals(IotDataSinkTcpConfig.DEFAULT_SSL,
+                ReflectUtil.getFieldValue(client, "ssl"));
+        assertEquals(IotDataSinkTcpConfig.DEFAULT_DATA_FORMAT,
+                ReflectUtil.getFieldValue(client, "dataFormat"));
+    }
+
+    @Test
+    public void testConstructor_customValues() {
+        // 准备参数
+        String host = "192.168.1.100";
+        Integer port = 9090;
+        Integer connectTimeoutMs = 3000;
+        Integer readTimeoutMs = 8000;
+        Boolean ssl = true;
+        String dataFormat = "BINARY";
+
+        // 调用
+        IotTcpClient client = new IotTcpClient(host, port, connectTimeoutMs, readTimeoutMs, ssl, dataFormat);
+
+        // 断言:验证自定义值
+        assertEquals(host, ReflectUtil.getFieldValue(client, "host"));
+        assertEquals(port, ReflectUtil.getFieldValue(client, "port"));
+        assertEquals(connectTimeoutMs, ReflectUtil.getFieldValue(client, "connectTimeoutMs"));
+        assertEquals(readTimeoutMs, ReflectUtil.getFieldValue(client, "readTimeoutMs"));
+        assertEquals(ssl, ReflectUtil.getFieldValue(client, "ssl"));
+        assertEquals(dataFormat, ReflectUtil.getFieldValue(client, "dataFormat"));
+    }
+
+    @Test
+    public void testIsConnected_initialState() {
+        // 准备参数
+        String host = "localhost";
+        Integer port = 8080;
+
+        // 调用
+        IotTcpClient client = new IotTcpClient(host, port, null, null, null, null);
+
+        // 断言:初始状态应为未连接
+        assertFalse(client.isConnected());
+    }
+
+    @Test
+    public void testToString() {
+        // 准备参数
+        String host = "localhost";
+        Integer port = 8080;
+
+        // 调用
+        IotTcpClient client = new IotTcpClient(host, port, null, null, null, null);
+        String result = client.toString();
+
+        // 断言
+        assertNotNull(result);
+        assertTrue(result.contains("host='localhost'"));
+        assertTrue(result.contains("port=8080"));
+        assertTrue(result.contains("dataFormat='JSON'"));
+        assertTrue(result.contains("connected=false"));
+    }
+
+}

+ 11 - 0
yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/util/IotDeviceMessageUtils.java

@@ -99,6 +99,17 @@ public class IotDeviceMessageUtils {
         return false;
     }
 
+    /**
+     * 判断消息中是否不包含指定的标识符
+     *
+     * @param message    消息
+     * @param identifier 要检查的标识符
+     * @return 是否不包含
+     */
+    public static boolean notContainsIdentifier(IotDeviceMessage message, String identifier) {
+        return !containsIdentifier(message, identifier);
+    }
+
     /**
      * 将 params 解析为 Map
      *

+ 70 - 2
yudao-module-iot/yudao-module-iot-core/src/test/java/cn/iocoder/yudao/module/iot/core/util/IotDeviceMessageUtilsTest.java

@@ -1,13 +1,13 @@
 package cn.iocoder.yudao.module.iot.core.util;
 
+import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageMethodEnum;
 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
 import org.junit.jupiter.api.Test;
 
 import java.util.HashMap;
 import java.util.Map;
 
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.*;
 
 /**
  * {@link IotDeviceMessageUtils} 的单元测试
@@ -138,4 +138,72 @@ public class IotDeviceMessageUtilsTest {
         Object result = IotDeviceMessageUtils.extractPropertyValue(message, "temperature");
         assertEquals(25.5, result); // 应该返回直接标识符的值
     }
+
+    // ========== notContainsIdentifier 测试 ==========
+
+    /**
+     * 测试 notContainsIdentifier 与 containsIdentifier 的互补性
+     * **Property 2: notContainsIdentifier 与 containsIdentifier 互补性**
+     * **Validates: Requirements 4.1**
+     */
+    @Test
+    public void testNotContainsIdentifier_complementary_whenContains() {
+        // 准备参数:消息包含指定标识符
+        IotDeviceMessage message = new IotDeviceMessage();
+        message.setMethod(IotDeviceMessageMethodEnum.PROPERTY_POST.getMethod());
+        Map<String, Object> params = new HashMap<>();
+        params.put("temperature", 25);
+        message.setParams(params);
+        String identifier = "temperature";
+
+        // 调用 & 断言:验证互补性
+        boolean containsResult = IotDeviceMessageUtils.containsIdentifier(message, identifier);
+        boolean notContainsResult = IotDeviceMessageUtils.notContainsIdentifier(message, identifier);
+        assertTrue(containsResult);
+        assertFalse(notContainsResult);
+        assertEquals(!containsResult, notContainsResult);
+    }
+
+    /**
+     * 测试 notContainsIdentifier 与 containsIdentifier 的互补性
+     * **Property 2: notContainsIdentifier 与 containsIdentifier 互补性**
+     * **Validates: Requirements 4.1**
+     */
+    @Test
+    public void testNotContainsIdentifier_complementary_whenNotContains() {
+        // 准备参数:消息不包含指定标识符
+        IotDeviceMessage message = new IotDeviceMessage();
+        message.setMethod(IotDeviceMessageMethodEnum.PROPERTY_POST.getMethod());
+        Map<String, Object> params = new HashMap<>();
+        params.put("temperature", 25);
+        message.setParams(params);
+        String identifier = "humidity";
+
+        // 调用 & 断言:验证互补性
+        boolean containsResult = IotDeviceMessageUtils.containsIdentifier(message, identifier);
+        boolean notContainsResult = IotDeviceMessageUtils.notContainsIdentifier(message, identifier);
+        assertFalse(containsResult);
+        assertTrue(notContainsResult);
+        assertEquals(!containsResult, notContainsResult);
+    }
+
+    /**
+     * 测试 notContainsIdentifier 与 containsIdentifier 的互补性 - 空参数场景
+     * **Property 2: notContainsIdentifier 与 containsIdentifier 互补性**
+     * **Validates: Requirements 4.1**
+     */
+    @Test
+    public void testNotContainsIdentifier_complementary_nullParams() {
+        // 准备参数:params 为 null
+        IotDeviceMessage message = new IotDeviceMessage();
+        message.setParams(null);
+        String identifier = "temperature";
+
+        // 调用 & 断言:验证互补性
+        boolean containsResult = IotDeviceMessageUtils.containsIdentifier(message, identifier);
+        boolean notContainsResult = IotDeviceMessageUtils.notContainsIdentifier(message, identifier);
+        assertFalse(containsResult);
+        assertTrue(notContainsResult);
+        assertEquals(!containsResult, notContainsResult);
+    }
 }