Bug 8977 - Failed on binary key type 30/61930/2
authorJakub Toth <jakub.toth@pantheon.tech>
Tue, 15 Aug 2017 15:07:14 +0000 (17:07 +0200)
committerJakub Morvay <jmorvay@cisco.com>
Tue, 22 Aug 2017 10:59:55 +0000 (12:59 +0200)
  * fix validating of uri with input data for binary key type
  * tests

Change-Id: I70ac6e10f9999bc0feca2ba600124fa639eef842
Signed-off-by: Jakub Toth <jakub.toth@pantheon.tech>
restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/restconf/impl/RestconfImpl.java
restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestconfImplTest.java

index 4abc492dff87e6bdadcd89e000507358faab2115..19a130fafe6f921aecda5c6f30ea8e7480dd00aa 100644 (file)
@@ -8,6 +8,7 @@
 
 package org.opendaylight.netconf.sal.restconf.impl;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.CharMatcher;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
@@ -37,6 +38,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.CancellationException;
 import java.util.concurrent.ExecutionException;
@@ -830,7 +832,7 @@ public class RestconfImpl implements RestconfService {
             try {
                 result.getFutureOfPutData().checkedGet();
                 return Response.status(result.getStatus()).build();
-            } catch (TransactionCommitFailedException e) {
+            } catch (final TransactionCommitFailedException e) {
                 if (e instanceof OptimisticLockFailedException) {
                     if (--tries <= 0) {
                         LOG.debug("Got OptimisticLockFailedException on last try - failing " + identifier);
@@ -893,7 +895,8 @@ public class RestconfImpl implements RestconfService {
         }
     }
 
-    private static void isEqualUriAndPayloadKeyValues(final Map<QName, Object> uriKeyValues, final MapEntryNode payload,
+    @VisibleForTesting
+    public static void isEqualUriAndPayloadKeyValues(final Map<QName, Object> uriKeyValues, final MapEntryNode payload,
             final List<QName> keyDefinitions) {
 
         final Map<QName, Object> mutableCopyUriKeyValues = Maps.newHashMap(uriKeyValues);
@@ -905,7 +908,7 @@ public class RestconfImpl implements RestconfService {
 
             final Object dataKeyValue = payload.getIdentifier().getKeyValues().get(keyDefinition);
 
-            if (!uriKeyValue.equals(dataKeyValue)) {
+            if (!Objects.deepEquals(uriKeyValue, dataKeyValue)) {
                 final String errMsg = "The value '" + uriKeyValue + "' for key '" + keyDefinition.getLocalName()
                         + "' specified in the URI doesn't match the value '" + dataKeyValue
                         + "' specified in the message body. ";
@@ -978,7 +981,7 @@ public class RestconfImpl implements RestconfService {
             future.checkedGet();
         } catch (final RestconfDocumentedException e) {
             throw e;
-        } catch (TransactionCommitFailedException e) {
+        } catch (final TransactionCommitFailedException e) {
             LOG.info("Error creating data " + (uriInfo != null ? uriInfo.getPath() : ""), e);
             throw new RestconfDocumentedException(e.getMessage(), e, e.getErrorList());
         }
@@ -1059,7 +1062,7 @@ public class RestconfImpl implements RestconfService {
 
         try {
             future.checkedGet();
-        } catch (TransactionCommitFailedException e) {
+        } catch (final TransactionCommitFailedException e) {
             final Optional<Throwable> searchedException = Iterables.tryFind(Throwables.getCausalChain(e),
                     Predicates.instanceOf(ModifiedNodeDoesNotExistException.class));
             if (searchedException.isPresent()) {
@@ -1173,7 +1176,7 @@ public class RestconfImpl implements RestconfService {
         final TemporalAccessor p;
         try {
             p = FORMATTER.parse(value);
-        } catch (DateTimeParseException e) {
+        } catch (final DateTimeParseException e) {
             throw new RestconfDocumentedException("Cannot parse of value in date: " + value, e);
         }
         return Instant.from(p);
index 37b0e595ce1ce798298e2f274dfbae1147a14295..c08b3349989469d993b880f86fc458d0e98ebef6 100644 (file)
@@ -24,8 +24,11 @@ import com.google.common.util.concurrent.Futures;
 import java.io.FileNotFoundException;
 import java.net.URI;
 import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
 import javax.ws.rs.core.MultivaluedHashMap;
@@ -43,14 +46,20 @@ import org.opendaylight.netconf.sal.restconf.impl.BrokerFacade;
 import org.opendaylight.netconf.sal.restconf.impl.ControllerContext;
 import org.opendaylight.netconf.sal.restconf.impl.InstanceIdentifierContext;
 import org.opendaylight.netconf.sal.restconf.impl.NormalizedNodeContext;
+import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
+import org.opendaylight.netconf.sal.restconf.impl.RestconfError;
+import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorType;
 import org.opendaylight.netconf.sal.restconf.impl.RestconfImpl;
 import org.opendaylight.netconf.sal.streams.listeners.Notificator;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
@@ -84,6 +93,44 @@ public class RestconfImplTest {
         this.restconfImpl.setControllerContext(controllerContext);
     }
 
+    @Test
+    public void binaryKeyTest() {
+        final List<Byte> al = new ArrayList<>();
+        al.add(new Byte((byte) 1));
+        binaryKeyTest(al, al);
+    }
+
+    private void binaryKeyTest(final List<Byte> al, final List<Byte> al2) {
+
+        final QName keyDef = QName.create("test:key:binary", "2017-14-08", "b1");
+
+        final Map<QName, Object> uriKeyValues = new HashMap<>();
+        uriKeyValues.put(keyDef, al.toArray());
+
+        final MapEntryNode payload = mock(MapEntryNode.class);
+        final NodeIdentifierWithPredicates nodeIdWithPred =
+                new NodeIdentifierWithPredicates(keyDef, keyDef, al2.toArray());
+        when(payload.getIdentifier()).thenReturn(nodeIdWithPred);
+
+        final List<QName> keyDefinitions = new ArrayList<>();
+        keyDefinitions.add(keyDef);
+        RestconfImpl.isEqualUriAndPayloadKeyValues(uriKeyValues, payload, keyDefinitions);
+    }
+
+    @Test
+    public void binaryKeyFailTest() {
+        final List<Byte> al = new ArrayList<>();
+        al.add(new Byte((byte) 1));
+        final List<Byte> al2 = new ArrayList<>();
+        try {
+            binaryKeyTest(al, al2);
+        } catch (final RestconfDocumentedException e) {
+            final RestconfError err = e.getErrors().iterator().next();
+            assertEquals(ErrorType.PROTOCOL, err.getErrorType());
+            assertEquals(ErrorTag.INVALID_VALUE, err.getErrorTag());
+        }
+    }
+
     @SuppressWarnings("unchecked")
     @Test
     public void testExample() throws FileNotFoundException, ParseException {