Normalize Decimal64 to fraction-digits 70/101270/11
authorRobert Varga <robert.varga@pantheon.tech>
Mon, 23 May 2022 18:19:57 +0000 (20:19 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Wed, 25 May 2022 11:20:39 +0000 (13:20 +0200)
When parsing a Decimal64, we need to scale it to fraction-digits
to ensure the input matches the expected range.

JIRA: YANGTOOLS-1437
Change-Id: I535eab4a20d30a742e94c3a6342e113cb569d0bf
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
data/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/DecimalStringCodec.java
data/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/codec/DecimalCodecStringTest.java
data/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/codec/YT1437Test.java [new file with mode: 0644]
data/yang-data-impl/src/test/resources/yt1437.yang [new file with mode: 0644]

index c3724ac142eb7dbeb38612c01629e0d0728c8011..a684e478f146887d204731179e007ceb025c58d4 100644 (file)
@@ -31,8 +31,17 @@ public final class DecimalStringCodec extends TypeDefinitionAwareCodec<Decimal64
 
     @Override
     protected Decimal64 deserializeImpl(final String product) {
-        // FIXME: run value validation
-        return Decimal64.valueOf(product);
+        final var typeDef = getTypeDefinition().orElseThrow();
+        final var parsed = Decimal64.valueOf(product);
+        final Decimal64 value;
+        try {
+            value = parsed.scaleTo(typeDef.getFractionDigits());
+        } catch (ArithmeticException e) {
+            throw new IllegalArgumentException("Value '" + product + "' does not match required fraction-digits", e);
+        }
+
+        // FIXME: check ranges
+        return value;
     }
 
     @Override
index fb3cc82375899cbd4576c9389c5423f07286fefa..8d564f0171dac689c1eda148978eb5df0982300f 100644 (file)
@@ -41,6 +41,6 @@ public class DecimalCodecStringTest {
     }
 
     private static DecimalTypeDefinition getType() {
-        return BaseTypes.decimalTypeBuilder(QName.create("foo", "foo")).setFractionDigits(2).build();
+        return BaseTypes.decimalTypeBuilder(QName.create("foo", "foo")).setFractionDigits(3).build();
     }
 }
diff --git a/data/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/codec/YT1437Test.java b/data/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/codec/YT1437Test.java
new file mode 100644 (file)
index 0000000..bfc220d
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2020 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.codec;
+
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
+
+public class YT1437Test {
+    @Test
+    public void testDecimalFractionDigits() {
+        final var module = YangParserTestUtils.parseYangResource("/yt1437.yang").findModule("yt1437").orElseThrow();
+        final var foo = module.findDataChildByName(QName.create(module.getQNameModule(), "foo")).orElseThrow();
+        assertThat(foo, instanceOf(LeafSchemaNode.class));
+
+        final TypeDefinitionAwareCodec<?, ?> codec = TypeDefinitionAwareCodec.from(((LeafSchemaNode) foo).getType());
+        assertThat(codec, instanceOf(DecimalStringCodec.class));
+        final var cast = (DecimalStringCodec) codec;
+
+        final var one = cast.deserialize("20.0");
+        assertEquals(2, one.scale());
+        assertEquals("20.0", cast.serialize(one));
+
+        final var two = cast.deserialize("20.00");
+        assertEquals(2, two.scale());
+        assertEquals("20.0", cast.serialize(two));
+
+        final var three = cast.deserialize("20.000");
+        assertEquals(2, three.scale());
+        assertEquals("20.0", cast.serialize(three));
+    }
+}
diff --git a/data/yang-data-impl/src/test/resources/yt1437.yang b/data/yang-data-impl/src/test/resources/yt1437.yang
new file mode 100644 (file)
index 0000000..2354605
--- /dev/null
@@ -0,0 +1,11 @@
+module yt1437 {
+  namespace yt1437;
+  prefix yt1437;
+
+  leaf foo {
+    type decimal64 {
+      fraction-digits 2;
+      range "20.0..30.01 | 50";
+    }
+  }
+}