This is an automated email from the ASF dual-hosted git repository.

Caideyipi pushed a commit to branch fix-equals-hashcode-contract-master
in repository https://gitbox.apache.org/repos/asf/iotdb.git

commit dbf88e5549458f753bb5244e9f9ee0cce8cdbc2d
Author: Caideyipi <[email protected]>
AuthorDate: Tue Jun 9 18:54:47 2026 +0800

    Fix equality hash code contracts
---
 .../org/apache/iotdb/pipe/api/type/Binary.java     | 18 +-----
 .../org/apache/iotdb/pipe/api/type/BinaryTest.java | 41 +++++++++++++
 .../manager/load/cache/node/NodeStatistics.java    |  2 +-
 .../load/cache/node/NodeStatisticsTest.java        | 37 ++++++++++++
 .../org/apache/iotdb/metrics/utils/MetricInfo.java | 12 +---
 .../apache/iotdb/metrics/utils/MetricInfoTest.java | 44 ++++++++++++++
 .../org/apache/iotdb/commons/auth/entity/User.java |  8 +--
 .../pipe/agent/plugin/meta/PipePluginMeta.java     |  2 +-
 .../agent/task/meta/PipeTemporaryMetaInAgent.java  |  2 +-
 .../iotdb/commons/trigger/TriggerInformation.java  | 16 +++++-
 .../task/meta/PipeTemporaryMetaInAgentTest.java    | 43 ++++++++++++++
 .../pipe/plugin/meta/PipePluginMetaTest.java       | 16 ++++++
 .../commons/trigger/TriggerInformationTest.java    | 67 ++++++++++++++++++++++
 .../apache/iotdb/commons/utils/AuthUtilsTest.java  | 53 +++++++++++++++++
 14 files changed, 324 insertions(+), 37 deletions(-)

diff --git 
a/iotdb-api/pipe-api/src/main/java/org/apache/iotdb/pipe/api/type/Binary.java 
b/iotdb-api/pipe-api/src/main/java/org/apache/iotdb/pipe/api/type/Binary.java
index 3a878f58a62..bb10042d66c 100644
--- 
a/iotdb-api/pipe-api/src/main/java/org/apache/iotdb/pipe/api/type/Binary.java
+++ 
b/iotdb-api/pipe-api/src/main/java/org/apache/iotdb/pipe/api/type/Binary.java
@@ -36,13 +36,6 @@ public class Binary implements Comparable<Binary>, 
Serializable {
 
   private final byte[] values;
 
-  private int hash;
-
-  // indicate whether hash has been calculated
-  private boolean hasCalculatedHash;
-
-  private String stringCache;
-
   /** if the bytes v is modified, the modification is visible to this binary. 
*/
   public Binary(byte[] v) {
     this.values = v;
@@ -94,11 +87,7 @@ public class Binary implements Comparable<Binary>, 
Serializable {
 
   @Override
   public int hashCode() {
-    if (!hasCalculatedHash) {
-      hash = Arrays.hashCode(values);
-      hasCalculatedHash = true;
-    }
-    return hash;
+    return Arrays.hashCode(values);
   }
 
   /**
@@ -121,10 +110,7 @@ public class Binary implements Comparable<Binary>, 
Serializable {
     if (values == null) {
       return null;
     }
-    if (stringCache == null) {
-      stringCache = new String(this.values, STRING_CHARSET);
-    }
-    return stringCache;
+    return new String(this.values, STRING_CHARSET);
   }
 
   public String getTextEncodingType() {
diff --git 
a/iotdb-api/pipe-api/src/test/java/org/apache/iotdb/pipe/api/type/BinaryTest.java
 
b/iotdb-api/pipe-api/src/test/java/org/apache/iotdb/pipe/api/type/BinaryTest.java
new file mode 100644
index 00000000000..ece56ca4395
--- /dev/null
+++ 
b/iotdb-api/pipe-api/src/test/java/org/apache/iotdb/pipe/api/type/BinaryTest.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.pipe.api.type;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class BinaryTest {
+
+  @Test
+  public void hashCodeUsesCurrentValues() {
+    byte[] values = new byte[] {'a'};
+    Binary binary = new Binary(values);
+    binary.hashCode();
+    binary.getStringValue();
+
+    values[0] = 'b';
+    Binary sameBinary = new Binary(new byte[] {'b'});
+
+    Assert.assertEquals(binary, sameBinary);
+    Assert.assertEquals(binary.hashCode(), sameBinary.hashCode());
+    Assert.assertEquals("b", binary.getStringValue());
+  }
+}
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/load/cache/node/NodeStatistics.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/load/cache/node/NodeStatistics.java
index 12c554d51e8..db302387cc7 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/load/cache/node/NodeStatistics.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/load/cache/node/NodeStatistics.java
@@ -81,7 +81,7 @@ public class NodeStatistics extends AbstractStatistics {
 
   @Override
   public int hashCode() {
-    return Objects.hash(status, statusReason, loadScore);
+    return Objects.hash(status, statusReason);
   }
 
   @Override
diff --git 
a/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/manager/load/cache/node/NodeStatisticsTest.java
 
b/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/manager/load/cache/node/NodeStatisticsTest.java
new file mode 100644
index 00000000000..badc3b51531
--- /dev/null
+++ 
b/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/manager/load/cache/node/NodeStatisticsTest.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.confignode.manager.load.cache.node;
+
+import org.apache.iotdb.commons.cluster.NodeStatus;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class NodeStatisticsTest {
+
+  @Test
+  public void hashCodeMatchesEqualsWhenOnlyLoadScoreDiffers() {
+    NodeStatistics lowLoadStatistics = new NodeStatistics(1, 
NodeStatus.Running, null, 1);
+    NodeStatistics highLoadStatistics = new NodeStatistics(2, 
NodeStatus.Running, null, 2);
+
+    Assert.assertEquals(lowLoadStatistics, highLoadStatistics);
+    Assert.assertEquals(lowLoadStatistics.hashCode(), 
highLoadStatistics.hashCode());
+  }
+}
diff --git 
a/iotdb-core/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/MetricInfo.java
 
b/iotdb-core/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/MetricInfo.java
index 416a143dc6e..fff70aa2529 100644
--- 
a/iotdb-core/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/MetricInfo.java
+++ 
b/iotdb-core/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/MetricInfo.java
@@ -177,20 +177,12 @@ public class MetricInfo {
         return false;
       }
       MetaInfo that = (MetaInfo) o;
-      if (tagNames == null || that.tagNames == null) {
-        return false;
-      }
-      for (String tagName : that.tagNames) {
-        if (!tagNames.contains(tagName)) {
-          return false;
-        }
-      }
-      return true;
+      return type == that.type && Objects.equals(tagNames, that.tagNames);
     }
 
     @Override
     public int hashCode() {
-      return Objects.hash(tagNames);
+      return Objects.hash(type, tagNames);
     }
 
     @Override
diff --git 
a/iotdb-core/metrics/interface/src/test/java/org/apache/iotdb/metrics/utils/MetricInfoTest.java
 
b/iotdb-core/metrics/interface/src/test/java/org/apache/iotdb/metrics/utils/MetricInfoTest.java
new file mode 100644
index 00000000000..0e42bf960b2
--- /dev/null
+++ 
b/iotdb-core/metrics/interface/src/test/java/org/apache/iotdb/metrics/utils/MetricInfoTest.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.metrics.utils;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class MetricInfoTest {
+
+  @Test
+  public void metaInfoEqualsHashCodeUsesTypeAndSameTagKeys() {
+    MetricInfo.MetaInfo metaInfo =
+        new MetricInfo(MetricType.COUNTER, "metric", "k1", "v1").getMetaInfo();
+    MetricInfo.MetaInfo sameMetaInfo =
+        new MetricInfo(MetricType.COUNTER, "metric", "k1", "v2").getMetaInfo();
+    MetricInfo.MetaInfo extraTagMetaInfo =
+        new MetricInfo(MetricType.COUNTER, "metric", "k1", "v1", "k2", 
"v2").getMetaInfo();
+    MetricInfo.MetaInfo differentTypeMetaInfo =
+        new MetricInfo(MetricType.GAUGE, "metric", "k1", "v1").getMetaInfo();
+
+    Assert.assertEquals(metaInfo, sameMetaInfo);
+    Assert.assertEquals(metaInfo.hashCode(), sameMetaInfo.hashCode());
+    Assert.assertNotEquals(metaInfo, extraTagMetaInfo);
+    Assert.assertNotEquals(extraTagMetaInfo, metaInfo);
+    Assert.assertNotEquals(metaInfo, differentTypeMetaInfo);
+  }
+}
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/entity/User.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/entity/User.java
index 0bebeaf8e06..32f45e218f3 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/entity/User.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/entity/User.java
@@ -178,13 +178,7 @@ public class User extends Role {
 
   @Override
   public int hashCode() {
-    return Objects.hash(
-        super.getName(),
-        password,
-        super.getPathPrivilegeList(),
-        super.getSysPrivilege(),
-        roleSet,
-        isOpenIdUser);
+    return Objects.hash(super.hashCode(), password, roleSet, isOpenIdUser);
   }
 
   @Override
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/pipe/agent/plugin/meta/PipePluginMeta.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/pipe/agent/plugin/meta/PipePluginMeta.java
index 19f6863be3c..4029419e4e3 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/pipe/agent/plugin/meta/PipePluginMeta.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/pipe/agent/plugin/meta/PipePluginMeta.java
@@ -170,7 +170,7 @@ public class PipePluginMeta {
 
   @Override
   public int hashCode() {
-    return pluginName.hashCode();
+    return Objects.hash(pluginName, className, isBuiltin, jarName, jarMD5);
   }
 
   @Override
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/pipe/agent/task/meta/PipeTemporaryMetaInAgent.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/pipe/agent/task/meta/PipeTemporaryMetaInAgent.java
index 23914fa8d84..5527622ca1b 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/pipe/agent/task/meta/PipeTemporaryMetaInAgent.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/pipe/agent/task/meta/PipeTemporaryMetaInAgent.java
@@ -92,7 +92,7 @@ public class PipeTemporaryMetaInAgent implements 
PipeTemporaryMeta {
 
   @Override
   public int hashCode() {
-    return Objects.hash(floatingMemoryUsageInByte, regionId2CommitterKeyMap);
+    return Objects.hash(floatingMemoryUsageInByte.get(), 
regionId2CommitterKeyMap);
   }
 
   @Override
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/trigger/TriggerInformation.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/trigger/TriggerInformation.java
index c25d185b0cd..5f2eea66dc5 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/trigger/TriggerInformation.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/trigger/TriggerInformation.java
@@ -157,6 +157,7 @@ public class TriggerInformation {
     TriggerInformation that = (TriggerInformation) o;
     return Objects.equals(triggerName, that.triggerName)
         && Objects.equals(pathPattern, that.pathPattern)
+        && isUsingURI == that.isUsingURI
         && isStateful == that.isStateful
         && Objects.equals(className, that.className)
         && Objects.equals(jarName, that.jarName)
@@ -164,12 +165,25 @@ public class TriggerInformation {
         && event == that.event
         && triggerState == that.triggerState
         && (!isStateful() || Objects.equals(dataNodeLocation, 
that.dataNodeLocation))
+        && failureStrategy == that.failureStrategy
         && Objects.equals(jarFileMD5, that.jarFileMD5);
   }
 
   @Override
   public int hashCode() {
-    return Objects.hash(triggerName);
+    return Objects.hash(
+        triggerName,
+        pathPattern,
+        isUsingURI,
+        isStateful,
+        className,
+        jarName,
+        attributes,
+        event,
+        triggerState,
+        isStateful ? dataNodeLocation : null,
+        failureStrategy,
+        jarFileMD5);
   }
 
   public PartialPath getPathPattern() {
diff --git 
a/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/pipe/agent/task/meta/PipeTemporaryMetaInAgentTest.java
 
b/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/pipe/agent/task/meta/PipeTemporaryMetaInAgentTest.java
new file mode 100644
index 00000000000..065a5a1dafb
--- /dev/null
+++ 
b/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/pipe/agent/task/meta/PipeTemporaryMetaInAgentTest.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.commons.pipe.agent.task.meta;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class PipeTemporaryMetaInAgentTest {
+
+  @Test
+  public void equalsHashCodeUsesFloatingMemoryValue() {
+    PipeTemporaryMetaInAgent meta = new PipeTemporaryMetaInAgent("pipe", 1);
+    meta.addFloatingMemoryUsageInByte(100);
+    meta.getCommitterKey("pipe", 1, 1, 0);
+
+    PipeTemporaryMetaInAgent sameMeta = new PipeTemporaryMetaInAgent("pipe", 
1);
+    sameMeta.addFloatingMemoryUsageInByte(100);
+    sameMeta.getCommitterKey("pipe", 1, 1, 0);
+
+    Assert.assertEquals(meta, sameMeta);
+    Assert.assertEquals(meta.hashCode(), sameMeta.hashCode());
+
+    sameMeta.decreaseFloatingMemoryUsageInByte(1);
+    Assert.assertNotEquals(meta, sameMeta);
+  }
+}
diff --git 
a/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/pipe/plugin/meta/PipePluginMetaTest.java
 
b/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/pipe/plugin/meta/PipePluginMetaTest.java
index b5b854adc4d..da9d493aecb 100644
--- 
a/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/pipe/plugin/meta/PipePluginMetaTest.java
+++ 
b/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/pipe/plugin/meta/PipePluginMetaTest.java
@@ -22,6 +22,7 @@ package org.apache.iotdb.commons.pipe.plugin.meta;
 import org.apache.iotdb.commons.pipe.agent.plugin.builtin.BuiltinPipePlugin;
 import 
org.apache.iotdb.commons.pipe.agent.plugin.meta.ConfigNodePipePluginMetaKeeper;
 import 
org.apache.iotdb.commons.pipe.agent.plugin.meta.DataNodePipePluginMetaKeeper;
+import org.apache.iotdb.commons.pipe.agent.plugin.meta.PipePluginMeta;
 
 import org.junit.Assert;
 import org.junit.Test;
@@ -32,6 +33,21 @@ import java.io.IOException;
 
 public class PipePluginMetaTest {
 
+  @Test
+  public void testPipePluginMetaHashCodeIncludesAllFields() {
+    PipePluginMeta pipePluginMeta =
+        new PipePluginMeta("test", "org.apache.iotdb.Test", false, "test.jar", 
"md5");
+    PipePluginMeta samePipePluginMeta =
+        new PipePluginMeta("TEST", "org.apache.iotdb.Test", false, "test.jar", 
"md5");
+    PipePluginMeta differentClassNamePipePluginMeta =
+        new PipePluginMeta("test", "org.apache.iotdb.AnotherTest", false, 
"test.jar", "md5");
+
+    Assert.assertEquals(pipePluginMeta, samePipePluginMeta);
+    Assert.assertEquals(pipePluginMeta.hashCode(), 
samePipePluginMeta.hashCode());
+    Assert.assertNotEquals(pipePluginMeta, differentClassNamePipePluginMeta);
+    Assert.assertNotEquals(pipePluginMeta.hashCode(), 
differentClassNamePipePluginMeta.hashCode());
+  }
+
   @Test
   public void testConfigNodePipePluginMetaKeeper() {
     ConfigNodePipePluginMetaKeeper keeper = new 
ConfigNodePipePluginMetaKeeper();
diff --git 
a/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/trigger/TriggerInformationTest.java
 
b/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/trigger/TriggerInformationTest.java
new file mode 100644
index 00000000000..e6dd037fac9
--- /dev/null
+++ 
b/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/trigger/TriggerInformationTest.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.commons.trigger;
+
+import org.apache.iotdb.commons.exception.IllegalPathException;
+import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.confignode.rpc.thrift.TTriggerState;
+import org.apache.iotdb.trigger.api.enums.FailureStrategy;
+import org.apache.iotdb.trigger.api.enums.TriggerEvent;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Collections;
+
+public class TriggerInformationTest {
+
+  @Test
+  public void equalsHashCodeIncludesUriUsageAndFailureStrategy() throws 
IllegalPathException {
+    TriggerInformation triggerInformation =
+        createTriggerInformation(true, FailureStrategy.OPTIMISTIC);
+    TriggerInformation sameTriggerInformation =
+        createTriggerInformation(true, FailureStrategy.OPTIMISTIC);
+
+    Assert.assertEquals(triggerInformation, sameTriggerInformation);
+    Assert.assertEquals(triggerInformation.hashCode(), 
sameTriggerInformation.hashCode());
+
+    Assert.assertNotEquals(
+        triggerInformation, createTriggerInformation(true, 
FailureStrategy.PESSIMISTIC));
+    Assert.assertNotEquals(
+        triggerInformation, createTriggerInformation(false, 
FailureStrategy.OPTIMISTIC));
+  }
+
+  private TriggerInformation createTriggerInformation(
+      boolean isUsingURI, FailureStrategy failureStrategy) throws 
IllegalPathException {
+    return new TriggerInformation(
+        new PartialPath("root.test.**"),
+        "trigger",
+        "trigger.class",
+        isUsingURI,
+        "trigger.jar",
+        Collections.singletonMap("k", "v"),
+        TriggerEvent.AFTER_INSERT,
+        TTriggerState.INACTIVE,
+        false,
+        null,
+        failureStrategy,
+        "jar-md5");
+  }
+}
diff --git 
a/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/utils/AuthUtilsTest.java
 
b/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/utils/AuthUtilsTest.java
index 7809d005e98..6500d8ab1db 100644
--- 
a/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/utils/AuthUtilsTest.java
+++ 
b/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/utils/AuthUtilsTest.java
@@ -22,6 +22,7 @@ package org.apache.iotdb.commons.utils;
 import org.apache.iotdb.commons.auth.AuthException;
 import org.apache.iotdb.commons.auth.entity.PathPrivilege;
 import org.apache.iotdb.commons.auth.entity.PrivilegeType;
+import org.apache.iotdb.commons.auth.entity.Role;
 import org.apache.iotdb.commons.auth.entity.User;
 import org.apache.iotdb.commons.conf.IoTDBConstant;
 import org.apache.iotdb.commons.exception.IllegalPathException;
@@ -136,6 +137,58 @@ public class AuthUtilsTest {
         AuthUtils.getPrivileges(path, 
privilegeList).contains(PrivilegeType.WRITE_DATA));
   }
 
+  @Test
+  public void authUtilsTest_PathPrivilegeEqualsIncludesGrantOption() throws 
IllegalPathException {
+    PathPrivilege withGrantOption = new PathPrivilege(new 
PartialPath("root.t1"));
+    withGrantOption.grantPrivilege(PrivilegeType.WRITE_SCHEMA, true);
+
+    PathPrivilege withoutGrantOption = new PathPrivilege(new 
PartialPath("root.t1"));
+    withoutGrantOption.grantPrivilege(PrivilegeType.WRITE_SCHEMA, false);
+
+    Assert.assertFalse(withGrantOption.equals(withoutGrantOption));
+
+    withoutGrantOption.grantPrivilege(PrivilegeType.WRITE_SCHEMA, true);
+    Assert.assertEquals(withGrantOption, withoutGrantOption);
+    Assert.assertEquals(withGrantOption.hashCode(), 
withoutGrantOption.hashCode());
+  }
+
+  @Test
+  public void authUtilsTest_RoleEqualsHashCodeIncludesSysGrantOption() {
+    Role withGrantOption = new Role("role");
+    withGrantOption.grantSysPrivilege(PrivilegeType.MANAGE_USER, true);
+
+    Role withoutGrantOption = new Role("role");
+    withoutGrantOption.grantSysPrivilege(PrivilegeType.MANAGE_USER, false);
+
+    Assert.assertFalse(withGrantOption.equals(withoutGrantOption));
+    Assert.assertNotEquals(withGrantOption.hashCode(), 
withoutGrantOption.hashCode());
+
+    withoutGrantOption.getSysPriGrantOpt().add(PrivilegeType.MANAGE_USER);
+    Assert.assertEquals(withGrantOption, withoutGrantOption);
+    Assert.assertEquals(withGrantOption.hashCode(), 
withoutGrantOption.hashCode());
+  }
+
+  @Test
+  public void authUtilsTest_UserEqualsHashCodeIncludesUserState() {
+    User user = new User("user", "password");
+    user.grantSysPrivilege(PrivilegeType.MANAGE_USER, true);
+    user.setOpenIdUser(true);
+
+    User userWithoutGrantOption = new User("user", "password");
+    userWithoutGrantOption.grantSysPrivilege(PrivilegeType.MANAGE_USER, false);
+    userWithoutGrantOption.setOpenIdUser(true);
+
+    Assert.assertFalse(user.equals(userWithoutGrantOption));
+    Assert.assertNotEquals(user.hashCode(), userWithoutGrantOption.hashCode());
+
+    userWithoutGrantOption.getSysPriGrantOpt().add(PrivilegeType.MANAGE_USER);
+    Assert.assertEquals(user, userWithoutGrantOption);
+    Assert.assertEquals(user.hashCode(), userWithoutGrantOption.hashCode());
+
+    userWithoutGrantOption.setOpenIdUser(false);
+    Assert.assertFalse(user.equals(userWithoutGrantOption));
+  }
+
   @Test
   public void authUtilsTest_PathPrivilegeAddRemove() throws 
IllegalPathException, AuthException {
     List<PathPrivilege> privs = new ArrayList<>();

Reply via email to