This is an automated email from the ASF dual-hosted git repository.
lhotari pushed a commit to branch branch-4.0
in repository https://gitbox.apache.org/repos/asf/pulsar.git
The following commit(s) were added to refs/heads/branch-4.0 by this push:
new ec4eef5ddae [fix][test] Made ProtobufNativeSchemaTest.testSchema
order-independent (#24805)
ec4eef5ddae is described below
commit ec4eef5ddae2ea9cff5a15b44ed42a8ed9228a2c
Author: Lucas Eby <[email protected]>
AuthorDate: Tue Nov 11 10:04:58 2025 -0600
[fix][test] Made ProtobufNativeSchemaTest.testSchema order-independent
(#24805)
(cherry picked from commit b8d0f142567a038545a9148cb518272751c3a4a8)
---
.../impl/schema/ProtobufNativeSchemaTest.java | 73 +++++++++++++++++++++-
1 file changed, 70 insertions(+), 3 deletions(-)
diff --git
a/pulsar-client/src/test/java/org/apache/pulsar/client/impl/schema/ProtobufNativeSchemaTest.java
b/pulsar-client/src/test/java/org/apache/pulsar/client/impl/schema/ProtobufNativeSchemaTest.java
index 59b282dec0c..a0ea3c1cc6e 100644
---
a/pulsar-client/src/test/java/org/apache/pulsar/client/impl/schema/ProtobufNativeSchemaTest.java
+++
b/pulsar-client/src/test/java/org/apache/pulsar/client/impl/schema/ProtobufNativeSchemaTest.java
@@ -20,14 +20,25 @@ package org.apache.pulsar.client.impl.schema;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.protobuf.DescriptorProtos;
import com.google.protobuf.Descriptors;
+import com.google.protobuf.InvalidProtocolBufferException;
+import com.google.protobuf.util.JsonFormat;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import java.nio.charset.StandardCharsets;
+import java.util.Base64;
import java.util.Collections;
import java.util.HashMap;
import lombok.extern.slf4j.Slf4j;
import org.apache.pulsar.common.schema.SchemaType;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.skyscreamer.jsonassert.JSONAssert;
+import org.skyscreamer.jsonassert.JSONCompareMode;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -46,6 +57,28 @@ public class ProtobufNativeSchemaTest {
+
"gBQjUKJW9yZy5hcGFjaGUucHVsc2FyLmNsaWVudC5zY2hlbWEucHJvdG9CDEV4dGVybmFsVGVzdGIGcHJvdG8z\",\"rootMessageT"
+
"ypeName\":\"proto.TestMessage\",\"rootFileDescriptorName\":\"Test.proto\"}";
+ private static final ObjectMapper MAPPER = new ObjectMapper();
+
+ /**
+ * Decode a base64-encoded Protobuf FileDescriptorSet into a canonical
JSON tree.
+ * @param b64 a base64 string
+ * @return a normalized JSON tree that can be compared with JSONAssert,
ensuring deterministic
+ * equality checks regardless of field ordering.
+ * @throws IllegalArgumentException if b64 isn't valid Base64
+ * @throws InvalidProtocolBufferException if the decoded bytes are not a
valid FileDescriptorSet
+ * @throws JSONException if the JSON string is invalid
+ */
+ private static JSONObject fdsToJson(String b64)
+ throws IllegalArgumentException, InvalidProtocolBufferException,
JSONException {
+ DescriptorProtos.FileDescriptorSet fds =
+
DescriptorProtos.FileDescriptorSet.parseFrom(Base64.getDecoder().decode(b64));
+ String json = JsonFormat.printer()
+ .includingDefaultValueFields()
+ .omittingInsignificantWhitespace()
+ .print(fds);
+ return new JSONObject(json);
+ }
+
@Test
public void testEncodeAndDecode() {
final String stringFieldValue = "StringFieldValue";
@@ -61,15 +94,49 @@ public class ProtobufNativeSchemaTest {
}
@Test
- public void testSchema() {
+ public void testSchema() throws Exception {
ProtobufNativeSchema<org.apache.pulsar.client.schema.proto.Test.TestMessage>
protobufSchema =
ProtobufNativeSchema.of(org.apache.pulsar.client.schema.proto.Test.TestMessage.class);
assertEquals(protobufSchema.getSchemaInfo().getType(),
SchemaType.PROTOBUF_NATIVE);
assertNotNull(ProtobufNativeSchemaUtils.deserialize(protobufSchema.getSchemaInfo().getSchema()));
- assertEquals(new String(protobufSchema.getSchemaInfo().getSchema(),
- StandardCharsets.UTF_8), EXPECTED_SCHEMA_JSON);
+
+ // Parse the actual/expected JSON into trees
+ String actualJson = new
String(protobufSchema.getSchemaInfo().getSchema(), StandardCharsets.UTF_8);
+ JsonNode actualRoot = MAPPER.readTree(actualJson);
+ JsonNode expectedRoot = MAPPER.readTree(EXPECTED_SCHEMA_JSON);
+
+ // Extract and validate the FileDescriptorSet field for semantic
comparison
+ // (When decoded, Protobuf descriptors can serialize fields in varying
orders
+ // causing hard coded string comparisons to fail)
+ String fdSetField = "fileDescriptorSet";
+ JsonNode actualB64Node = actualRoot.path(fdSetField);
+ JsonNode expectedB64Node = expectedRoot.path(fdSetField);
+ Assert.assertFalse(actualB64Node.isMissingNode());
+ Assert.assertFalse(expectedB64Node.isMissingNode());
+ Assert.assertTrue(actualB64Node.isValueNode());
+ Assert.assertTrue(expectedB64Node.isValueNode());
+
+ // Decode FileDescriptorSets to JSON and compare semantically
(order-insensitive)
+ JSONObject actualFdsObj = fdsToJson(actualB64Node.asText());
+ JSONObject expectedFdsObj = fdsToJson(expectedB64Node.asText());
+ JSONAssert.assertEquals(
+ "FileDescriptorSet mismatch: decoded Protobuf descriptors have
mismatched schema contents",
+ expectedFdsObj,
+ actualFdsObj,
+ JSONCompareMode.NON_EXTENSIBLE
+ );
+
+ // Remove the already verified field and compare remaining schema
attributes, order does not matter
+ ((ObjectNode) actualRoot).remove(fdSetField);
+ ((ObjectNode) expectedRoot).remove(fdSetField);
+ JSONAssert.assertEquals(
+ "Schema metadata mismatch: remaining JSON fields differ after
verifying FileDescriptorSet",
+ MAPPER.writeValueAsString(expectedRoot),
+ MAPPER.writeValueAsString(actualRoot),
+ JSONCompareMode.NON_EXTENSIBLE
+ );
}
@Test