Improve error path for list items 96/110096/3
authorYaroslav Lastivka <yaroslav.lastivka@pantheon.tech>
Wed, 31 Jan 2024 09:26:01 +0000 (11:26 +0200)
committerIvan Hrasko <ivan.hrasko@pantheon.tech>
Tue, 6 Feb 2024 12:54:08 +0000 (12:54 +0000)
Enhanced the throwing of RestconfDocumentedException
to include a more precise path.

JIRA: NETCONF-1222
Change-Id: I19f9b7c413ba24a38d716c2140ad35ef94c5ff49
Signed-off-by: Yaroslav Lastivka <yaroslav.lastivka@pantheon.tech>
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/transactions/MdsalRestconfTransaction.java
restconf/restconf-nb/src/test/java/org/opendaylight/restconf/nb/jaxrs/RestconfDataPostTest.java

index ea040a404509780bc121243b03ac4eaad910b970..7d57d36cdf848b27ae1e1c04510b94fd30856fb2 100644 (file)
@@ -89,9 +89,9 @@ final class MdsalRestconfTransaction extends RestconfTransaction {
             }
 
             // ... finally collect existence checks and abort the transaction if any of them failed.
-            if (check.getOrThrow() instanceof Conflict) {
+            if (check.getOrThrow() instanceof Conflict conflict) {
                 throw new RestconfDocumentedException("Data already exists", ErrorType.PROTOCOL, ErrorTag.DATA_EXISTS,
-                    path);
+                    conflict.path());
             }
         } else {
             RestconfStrategy.checkItemDoesNotExists(verifyNotNull(rwTx).exists(CONFIGURATION, path), path);
index 9d060a3e57ec4e8459fffbeda68d67b3dde38742..205fd4af0c29d420612cba23f9e4f0b826ada2eb 100644 (file)
@@ -12,7 +12,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.lenient;
-import static org.mockito.Mockito.mock;
 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFalseFluentFuture;
 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateTrueFluentFuture;
 
@@ -31,6 +30,8 @@ import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
 import org.opendaylight.yangtools.yang.common.ErrorTag;
 import org.opendaylight.yangtools.yang.common.ErrorType;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.spi.node.ImmutableNodes;
 
@@ -38,6 +39,8 @@ import org.opendaylight.yangtools.yang.data.spi.node.ImmutableNodes;
 class RestconfDataPostTest extends AbstractRestconfTest {
     @Mock
     private DOMDataTreeReadWriteTransaction tx;
+    @Mock
+    private AsyncResponse asyncResponse;
 
     @BeforeEach
     void beforeEach() {
@@ -84,7 +87,6 @@ class RestconfDataPostTest extends AbstractRestconfTest {
         doReturn(new MultivaluedHashMap<>()).when(uriInfo).getQueryParameters();
         doReturn(immediateTrueFluentFuture())
             .when(tx).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
-        final var mockAsyncResponse = mock(AsyncResponse.class);
 
         final var ex = assertThrows(RestconfDocumentedException.class, () -> restconf
             .postDataJSON(stringInputStream("""
@@ -92,10 +94,33 @@ class RestconfDataPostTest extends AbstractRestconfTest {
                   "example-jukebox:jukebox" : {
                   }
                 }"""),
-            uriInfo, mockAsyncResponse));
+            uriInfo, asyncResponse));
 
         final var error = ex.getErrors().get(0);
         assertEquals(ErrorType.PROTOCOL, error.getErrorType());
         assertEquals(ErrorTag.DATA_EXISTS, error.getErrorTag());
     }
+
+    @Test
+    public void testPostExistingListsDataErrorPath() {
+        doReturn(new MultivaluedHashMap<>()).when(uriInfo).getQueryParameters();
+        final var node = PLAYLIST_IID.node(BAND_ENTRY.name());
+        doReturn(immediateTrueFluentFuture()).when(tx).exists(LogicalDatastoreType.CONFIGURATION, node);
+        doNothing().when(tx).put(LogicalDatastoreType.CONFIGURATION, node, BAND_ENTRY);
+
+        final var ex = assertThrows(RestconfDocumentedException.class, () -> restconf.postDataJSON(JUKEBOX_API_PATH,
+            stringInputStream("""
+                {
+                  "example-jukebox:playlist" : {
+                    "name" : "name of band",
+                    "description" : "band description"
+                  }
+                }"""),
+                uriInfo, asyncResponse));
+        final var actualPath = ex.getErrors().get(0).getErrorPath();
+        final var expectedPath = YangInstanceIdentifier.builder(PLAYLIST_IID)
+            .nodeWithKey(PLAYLIST_QNAME, QName.create(JUKEBOX_QNAME, "name"), "name of band")
+            .build();
+        assertEquals(expectedPath, actualPath);
+    }
 }