FrankYang0529 commented on code in PR #19523:
URL: https://github.com/apache/kafka/pull/19523#discussion_r2087037433


##########
group-coordinator/src/test/java/org/apache/kafka/coordinator/group/UtilsTest.java:
##########
@@ -0,0 +1,207 @@
+/*
+ * 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.kafka.coordinator.group;
+
+import org.apache.kafka.common.Uuid;
+import org.apache.kafka.image.MetadataImage;
+
+import com.dynatrace.hash4j.hashing.Hashing;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.io.IOException;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+
+public class UtilsTest {
+    private static final Uuid FOO_TOPIC_ID = Uuid.randomUuid();
+    private static final String FOO_TOPIC_NAME = "foo";
+    private static final String BAR_TOPIC_NAME = "bar";
+    private static final int FOO_NUM_PARTITIONS = 2;
+    private static final MetadataImage FOO_METADATA_IMAGE = new 
MetadataImageBuilder()
+        .addTopic(FOO_TOPIC_ID, FOO_TOPIC_NAME, FOO_NUM_PARTITIONS)
+        .addRacks()
+        .build();
+
+    @Test
+    void testComputeTopicHash() throws IOException {
+        long result = 
Utils.computeTopicHash(FOO_METADATA_IMAGE.topics().getTopic(FOO_TOPIC_ID), 
FOO_METADATA_IMAGE.cluster());

Review Comment:
   If input is topic name and metadata image, we need to handle null 
`TopicImage` in `computeTopicHash`. Do we want to handle this error in it?



##########
group-coordinator/src/test/java/org/apache/kafka/coordinator/group/UtilsTest.java:
##########
@@ -0,0 +1,207 @@
+/*
+ * 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.kafka.coordinator.group;
+
+import org.apache.kafka.common.Uuid;
+import org.apache.kafka.image.MetadataImage;
+
+import com.dynatrace.hash4j.hashing.Hashing;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.io.IOException;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+
+public class UtilsTest {
+    private static final Uuid FOO_TOPIC_ID = Uuid.randomUuid();
+    private static final String FOO_TOPIC_NAME = "foo";
+    private static final String BAR_TOPIC_NAME = "bar";
+    private static final int FOO_NUM_PARTITIONS = 2;
+    private static final MetadataImage FOO_METADATA_IMAGE = new 
MetadataImageBuilder()
+        .addTopic(FOO_TOPIC_ID, FOO_TOPIC_NAME, FOO_NUM_PARTITIONS)
+        .addRacks()
+        .build();
+
+    @Test
+    void testComputeTopicHash() throws IOException {
+        long result = 
Utils.computeTopicHash(FOO_METADATA_IMAGE.topics().getTopic(FOO_TOPIC_ID), 
FOO_METADATA_IMAGE.cluster());
+
+        long expected = Hashing.xxh3_64().hashStream()
+            .putByte((byte) 0) // magic byte
+            .putLong(FOO_TOPIC_ID.hashCode()) // topic ID
+            .putString(FOO_TOPIC_NAME) // topic name
+            .putInt(FOO_NUM_PARTITIONS) // number of partitions
+            .putInt(0) // partition 0
+            .putInt(5) // length of rack0
+            .putString("rack0") // The first rack in partition 0
+            .putInt(5) // length of rack1
+            .putString("rack1") // The second rack in partition 0
+            .putInt(1) // partition 1
+            .putInt(5) // length of rack0
+            .putString("rack1") // The first rack in partition 1
+            .putInt(5) // length of rack1
+            .putString("rack2") // The second rack in partition 1
+            .getAsLong();
+        assertEquals(expected, result);
+    }
+
+    @Test
+    void testComputeTopicHashWithDifferentMagicByte() throws IOException {
+        long result = 
Utils.computeTopicHash(FOO_METADATA_IMAGE.topics().getTopic(FOO_TOPIC_ID), 
FOO_METADATA_IMAGE.cluster());
+
+        long expected = Hashing.xxh3_64().hashStream()
+            .putByte((byte) 1) // magic byte
+            .putLong(FOO_TOPIC_ID.hashCode()) // topic ID
+            .putString(FOO_TOPIC_NAME) // topic name
+            .putInt(FOO_NUM_PARTITIONS) // number of partitions
+            .putInt(0) // partition 0
+            .putInt(5) // length of rack0
+            .putString("rack0") // The first rack in partition 0
+            .putInt(5) // length of rack1
+            .putString("rack1") // The second rack in partition 0
+            .putInt(1) // partition 1
+            .putInt(5) // length of rack0
+            .putString("rack1") // The first rack in partition 1
+            .putInt(5) // length of rack1
+            .putString("rack2") // The second rack in partition 1
+            .getAsLong();
+        assertNotEquals(expected, result);
+    }
+
+    @Test
+    void testComputeTopicHashWithDifferentPartitionOrder() throws IOException {
+        long result = 
Utils.computeTopicHash(FOO_METADATA_IMAGE.topics().getTopic(FOO_TOPIC_ID), 
FOO_METADATA_IMAGE.cluster());
+
+        long expected = Hashing.xxh3_64().hashStream()
+            .putByte((byte) 1) // magic byte
+            .putLong(FOO_TOPIC_ID.hashCode()) // topic ID
+            .putString(FOO_TOPIC_NAME) // topic name
+            .putInt(FOO_NUM_PARTITIONS) // number of partitions
+            .putInt(1) // partition 1
+            .putInt(5) // length of rack0
+            .putString("rack1") // The first rack in partition 1
+            .putInt(5) // length of rack1
+            .putString("rack2") // The second rack in partition 1
+            .putInt(0) // partition 0
+            .putInt(5) // length of rack0
+            .putString("rack0") // The first rack in partition 0
+            .putInt(5) // length of rack1
+            .putString("rack1") // The second rack in partition 0
+            .getAsLong();
+        assertNotEquals(expected, result);
+    }
+
+    @Test
+    void testComputeTopicHashWithDifferentRackOrder() throws IOException {
+        long result = 
Utils.computeTopicHash(FOO_METADATA_IMAGE.topics().getTopic(FOO_TOPIC_ID), 
FOO_METADATA_IMAGE.cluster());
+
+        long expected = Hashing.xxh3_64().hashStream()
+            .putByte((byte) 0) // magic byte
+            .putLong(FOO_TOPIC_ID.hashCode()) // topic ID
+            .putString(FOO_TOPIC_NAME) // topic name
+            .putInt(FOO_NUM_PARTITIONS) // number of partitions
+            .putInt(0) // partition 0
+            .putInt(5) // length of rack0
+            .putString("rack1") // The second rack in partition 0
+            .putInt(5) // length of rack1
+            .putString("rack0") // The first rack in partition 0
+            .putInt(1) // partition 1
+            .putInt(5) // length of rack0
+            .putString("rack1") // The first rack in partition 1
+            .putInt(5) // length of rack1
+            .putString("rack2") // The second rack in partition 1
+            .getAsLong();
+        assertNotEquals(expected, result);
+    }
+
+    @ParameterizedTest
+    @MethodSource("differentFieldGenerator")
+    void testComputeTopicHashWithDifferentField(MetadataImage differentImage, 
Uuid topicId) throws IOException {
+        long result = 
Utils.computeTopicHash(FOO_METADATA_IMAGE.topics().getTopic(FOO_TOPIC_ID), 
FOO_METADATA_IMAGE.cluster());
+
+        assertNotEquals(
+            Utils.computeTopicHash(
+                differentImage.topics().getTopic(topicId),
+                differentImage.cluster()
+            ),
+            result
+        );
+    }
+
+    private static Stream<Arguments> differentFieldGenerator() {
+        Uuid differentTopicId = Uuid.randomUuid();
+        return Stream.of(
+            Arguments.of(new MetadataImageBuilder() // different topic id
+                    .addTopic(differentTopicId, FOO_TOPIC_NAME, 
FOO_NUM_PARTITIONS)
+                    .addRacks()
+                    .build(),
+                differentTopicId
+            ),

Review Comment:
   Updated it. Thanks.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: jira-unsubscr...@kafka.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to