Fix boolean parsing leniency 92/89092/3
authorRobert Varga <robert.varga@pantheon.tech>
Fri, 17 Apr 2020 10:46:00 +0000 (12:46 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Fri, 17 Apr 2020 10:57:55 +0000 (12:57 +0200)
RFC7950 explicitly requires that booleans be encoded as lower-case
"true" or "false", not anything else. Our attempt at leniency misfires
as we are doing the wrong thing if a boolean is coupled with a string
in a union.

JIRA: YANGTOOLS-1097
Change-Id: I6da2f22db7bfb57eec7b519663f2a84fee735cd0
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/BooleanStringCodec.java
yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/codec/BooleanCodecStringTest.java
yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/codec/YT1097Test.java [new file with mode: 0644]
yang/yang-data-impl/src/test/resources/yt1097.yang [new file with mode: 0644]

index 9dcf2a18f6453db7ea39455e303825596f67264f..643b4a8413821d791e43ffc94d6c8f611b98c245 100644 (file)
@@ -30,14 +30,14 @@ public final class BooleanStringCodec extends TypeDefinitionAwareCodec<Boolean,
 
     @Override
     protected Boolean deserializeImpl(final String product) {
-        // FIXME: should forbid "TRUE" ?
-        if ("true".equalsIgnoreCase(product)) {
-            return Boolean.TRUE;
-        } else if ("false".equalsIgnoreCase(product)) {
-            return Boolean.FALSE;
-        } else {
-            throw new IllegalArgumentException("Invalid value '" + product + "' for boolean type. Allowed values are "
-                    + "'true' and 'false'");
+        switch (product) {
+            case "true":
+                return Boolean.TRUE;
+            case "false":
+                return Boolean.FALSE;
+            default:
+                throw new IllegalArgumentException("Invalid value '" + product + "' for boolean type. Allowed values "
+                    + "are 'true' and 'false'");
         }
     }
 
index 8fc01bd9d81786c37fb70e04f514cee0a39e7609..8a4c013c83926d9a6dcde016cdbda1a8d8117abd 100644 (file)
@@ -36,9 +36,9 @@ public class BooleanCodecStringTest {
             BooleanCodec.class);
 
         assertEquals("deserialize", Boolean.TRUE, codec.deserialize("true"));
-        assertEquals("deserialize", Boolean.TRUE, codec.deserialize("TRUE"));
-        assertEquals("deserialize", Boolean.FALSE, codec.deserialize("FALSE"));
         assertEquals("deserialize", Boolean.FALSE, codec.deserialize("false"));
+        TypeDefinitionAwareCodecTestHelper.deserializeWithExpectedIllegalArgEx(codec, "TRUE");
+        TypeDefinitionAwareCodecTestHelper.deserializeWithExpectedIllegalArgEx(codec, "FALSE");
         TypeDefinitionAwareCodecTestHelper.deserializeWithExpectedIllegalArgEx(codec, "foo");
         TypeDefinitionAwareCodecTestHelper.deserializeWithExpectedIllegalArgEx(codec, "");
     }
diff --git a/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/codec/YT1097Test.java b/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/codec/YT1097Test.java
new file mode 100644 (file)
index 0000000..aa9d83b
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
+
+public class YT1097Test {
+    @Test
+    public void testBooleanStringUnion() {
+        final Module module = YangParserTestUtils.parseYangResource("/yt1097.yang").findModule("yt1097").orElseThrow();
+        final DataSchemaNode 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(UnionStringCodec.class));
+
+        assertDecoded(codec, Boolean.TRUE, "true");
+        assertDecoded(codec, Boolean.FALSE, "false");
+        assertDecoded(codec, "True");
+        assertDecoded(codec, "TRUE");
+        assertDecoded(codec, "False");
+        assertDecoded(codec, "FALSE");
+    }
+
+    private static void assertDecoded(final TypeDefinitionAwareCodec<?, ?> codec, final String input) {
+        assertDecoded(codec, input, input);
+    }
+
+    private static void assertDecoded(final TypeDefinitionAwareCodec<?, ?> codec, final Object expected,
+            final String input) {
+        final Object result = codec.deserialize(input);
+        assertThat(result, instanceOf(expected.getClass()));
+        assertEquals(expected, result);
+    }
+}
diff --git a/yang/yang-data-impl/src/test/resources/yt1097.yang b/yang/yang-data-impl/src/test/resources/yt1097.yang
new file mode 100644 (file)
index 0000000..904f384
--- /dev/null
@@ -0,0 +1,12 @@
+module yt1097 {
+  namespace yt1097;
+  prefix yt1097;
+
+  leaf foo {
+    type union {
+      type boolean;
+      type string;
+    }
+  }
+}
+