From 1cea0782316eb79df3f76338bd01144d19a03c9e Mon Sep 17 00:00:00 2001 From: Krisso Date: Tue, 29 Aug 2023 22:52:03 +0200 Subject: [PATCH] [fastserde] Fix issue with generating schema fingerprint when NaN is a default value. --- .../src/test/avro/floatWithDefaultNaN.avsc | 13 +++++++++++ .../linkedin/avro/fastserde/UtilsTest.java | 23 +++++++++++++++++++ .../compatibility/Jackson2Utils.java | 5 ++-- 3 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 fastserde/avro-fastserde-tests-common/src/test/avro/floatWithDefaultNaN.avsc diff --git a/fastserde/avro-fastserde-tests-common/src/test/avro/floatWithDefaultNaN.avsc b/fastserde/avro-fastserde-tests-common/src/test/avro/floatWithDefaultNaN.avsc new file mode 100644 index 000000000..bddc35d88 --- /dev/null +++ b/fastserde/avro-fastserde-tests-common/src/test/avro/floatWithDefaultNaN.avsc @@ -0,0 +1,13 @@ +{ + "type": "record", + "name": "FloatWithDefaultNaN", + "namespace": "com.linkedin.avro.fastserde.generated.avro", + "doc": "Used to verify Utils.getSchemaFingerprint() method", + "fields": [ + { + "name": "floatWithDefaultNaN", + "type": "float", + "default": "NaN" + } + ] +} diff --git a/fastserde/avro-fastserde-tests-common/src/test/java/com/linkedin/avro/fastserde/UtilsTest.java b/fastserde/avro-fastserde-tests-common/src/test/java/com/linkedin/avro/fastserde/UtilsTest.java index 74026687d..855396d4d 100644 --- a/fastserde/avro-fastserde-tests-common/src/test/java/com/linkedin/avro/fastserde/UtilsTest.java +++ b/fastserde/avro-fastserde-tests-common/src/test/java/com/linkedin/avro/fastserde/UtilsTest.java @@ -3,6 +3,8 @@ import org.testng.Assert; import org.testng.annotations.Test; +import com.linkedin.avro.fastserde.generated.avro.FloatWithDefaultNaN; + public class UtilsTest { @@ -10,4 +12,25 @@ public class UtilsTest { public void testGenerateSourcePathFromPackageName() { Assert.assertEquals(Utils.generateSourcePathFromPackageName("com.linkedin.avro"), Utils.fixSeparatorsToMatchOS("/com/linkedin/avro/")); } + + @Test + void testDefaultValueNaN() { + // given + FloatWithDefaultNaN floatWithDefaultNaN = FloatWithDefaultNaN.newBuilder().build(); + + // when + float defaultValue = floatWithDefaultNaN.getFloatWithDefaultNaN(); + + // then + Assert.assertTrue(Float.isNaN(defaultValue)); + } + + @Test + void testFingerprintOfSchemaWithDefaultNaN() { + // when + int schemaFingerprint = Utils.getSchemaFingerprint(FloatWithDefaultNaN.SCHEMA$); + + // then + Assert.assertEquals(schemaFingerprint, 502051122); + } } diff --git a/helper/helper-common/src/main/java/com/linkedin/avroutil1/compatibility/Jackson2Utils.java b/helper/helper-common/src/main/java/com/linkedin/avroutil1/compatibility/Jackson2Utils.java index 445aac29e..df6b1b6c1 100644 --- a/helper/helper-common/src/main/java/com/linkedin/avroutil1/compatibility/Jackson2Utils.java +++ b/helper/helper-common/src/main/java/com/linkedin/avroutil1/compatibility/Jackson2Utils.java @@ -143,20 +143,19 @@ public static boolean isRoundNumber(JsonNode node) { * Enforces uniform numeric default values across Avro versions */ public static JsonNode enforceUniformNumericDefaultValues(Schema.Field field, JsonNode genericDefaultValue) { - BigDecimal numericDefaultValue = genericDefaultValue.decimalValue(); Schema schema = field.schema(); // a default value for a union, must match the first element of the union Schema.Type defaultType = schema.getType() == UNION ? schema.getTypes().get(0).getType() : schema.getType(); switch (defaultType) { case INT: - if (!isAMathematicalInteger(numericDefaultValue)) { + if (!isAMathematicalInteger(genericDefaultValue.decimalValue())) { LOGGER.warn(String.format("Invalid default value: %s for \"int\" field: %s", genericDefaultValue, field.name())); return genericDefaultValue; } return new IntNode(genericDefaultValue.intValue()); case LONG: - if (!isAMathematicalInteger(numericDefaultValue)) { + if (!isAMathematicalInteger(genericDefaultValue.decimalValue())) { LOGGER.warn(String.format("Invalid default value: %s for \"long\" field: %s", genericDefaultValue, field.name())); return genericDefaultValue; }