import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFailedFluentFuture;
import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFluentFuture;
import com.google.common.util.concurrent.Futures;
+import java.text.ParseException;
+import java.util.HashMap;
import java.util.Optional;
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.mdsal.dom.spi.DefaultDOMRpcResult;
import org.opendaylight.netconf.api.NetconfDocumentedException;
import org.opendaylight.netconf.dom.api.NetconfDataTreeService;
+import org.opendaylight.restconf.api.ApiPath;
import org.opendaylight.restconf.common.patch.PatchStatusContext;
import org.opendaylight.restconf.common.patch.PatchStatusEntity;
+import org.opendaylight.restconf.nb.rfc8040.databind.JsonDataPostBody;
+import org.opendaylight.restconf.nb.rfc8040.databind.JsonResourceBody;
import org.opendaylight.restconf.server.api.DatabindContext;
import org.opendaylight.yangtools.yang.common.ErrorSeverity;
import org.opendaylight.yangtools.yang.common.ErrorTag;
import org.opendaylight.yangtools.yang.common.ErrorType;
+import org.opendaylight.yangtools.yang.common.Uint32;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.spi.node.ImmutableNodes;
import org.w3c.dom.DOMException;
@RunWith(MockitoJUnitRunner.StrictStubs.class)
Optional.empty());
}
+ /**
+ * Test for put with insert=after option for last element of the list. Here we're trying to insert new element of
+ * the ordered list after last existing element. Test uses list with two items and add third one at the end. After
+ * this we check how many times replace transaction was called to know how many items was inserted.
+ * @throws ParseException if ApiPath string cannot be parsed
+ */
+ @Test
+ public void testPutDataWithInsertAfterLast() throws ParseException {
+ // Spy of jukeboxStrategy will be used later to count how many items was inserted
+ final var spyStrategy = spy(jukeboxStrategy());
+ final var spyTx = spy(jukeboxStrategy().prepareWriteExecution());
+ doReturn(spyTx).when(spyStrategy).prepareWriteExecution();
+ doReturn(immediateFluentFuture(Optional.empty())).when(netconfService).getConfig(any());
+
+ // For this test we are using
+ final var songsList = ImmutableNodes.newUserMapBuilder()
+ .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(SONG_QNAME))
+ .withChild(ImmutableNodes.newMapEntryBuilder()
+ .withNodeIdentifier(YangInstanceIdentifier.NodeIdentifierWithPredicates.of(SONG_QNAME, SONG_INDEX_QNAME,
+ Uint32.valueOf(1)))
+ .withChild(ImmutableNodes.leafNode(SONG_ID_QNAME, "A"))
+ .build())
+ .withChild(ImmutableNodes.newMapEntryBuilder()
+ .withNodeIdentifier(YangInstanceIdentifier.NodeIdentifierWithPredicates.of(SONG_QNAME, SONG_INDEX_QNAME,
+ Uint32.valueOf(2)))
+ .withChild(ImmutableNodes.leafNode(SONG_ID_QNAME, "B"))
+ .build())
+ .build();
+ doReturn(songsList).when(spyTx).readList(any(YangInstanceIdentifier.class));
+
+ // Creating query params to insert new item after last existing item in list
+ final var queryParams = new HashMap<String, String>();
+ queryParams.put("insert", "after");
+ queryParams.put("point", "example-jukebox:jukebox/playlist=0/song=2");
+
+ // Inserting new song at 3rd position (aka as last element)
+ spyStrategy.dataPUT(ApiPath.parse("example-jukebox:jukebox/playlist=0/song=3"),
+ new JsonResourceBody(stringInputStream("""
+ {
+ "example-jukebox:song" : [
+ {
+ "index": "3",
+ "id" = "C"
+ }
+ ]
+ }""")), queryParams);
+
+ // Counting how many times we insert items in list
+ verify(spyTx, times(3)).replace(any(), any());
+ }
+
+ /**
+ * Test for post with insert=after option for last element of the list. Here we're trying to insert new element of
+ * the ordered list after last existing element. Test uses list with two items and add third one at the end. After
+ * this we check how many times replace transaction was called to know how many items was inserted.
+ * @throws ParseException if ApiPath string cannot be parsed
+ */
+ @Test
+ public void testPostDataWithInsertAfterLast() throws ParseException {
+ // Spy of jukeboxStrategy will be used later to count how many items was inserted
+ final var spyStrategy = spy(jukeboxStrategy());
+ final var spyTx = spy(jukeboxStrategy().prepareWriteExecution());
+ doReturn(spyTx).when(spyStrategy).prepareWriteExecution();
+ doReturn(immediateFluentFuture(Optional.empty())).when(netconfService).getConfig(any());
+
+ // For this test we are using
+ final var songsList = ImmutableNodes.newUserMapBuilder()
+ .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(SONG_QNAME))
+ .withChild(ImmutableNodes.newMapEntryBuilder()
+ .withNodeIdentifier(YangInstanceIdentifier.NodeIdentifierWithPredicates.of(SONG_QNAME,
+ SONG_INDEX_QNAME, Uint32.valueOf(1)))
+ .withChild(ImmutableNodes.leafNode(SONG_ID_QNAME, "A"))
+ .build())
+ .withChild(ImmutableNodes.newMapEntryBuilder()
+ .withNodeIdentifier(YangInstanceIdentifier.NodeIdentifierWithPredicates.of(SONG_QNAME,
+ SONG_INDEX_QNAME, Uint32.valueOf(2)))
+ .withChild(ImmutableNodes.leafNode(SONG_ID_QNAME, "B"))
+ .build())
+ .build();
+ doReturn(songsList).when(spyTx).readList(any(YangInstanceIdentifier.class));
+
+ // Creating query params to insert new item after last existing item in list
+ final var queryParams = new HashMap<String, String>();
+ queryParams.put("insert", "after");
+ queryParams.put("point", "example-jukebox:jukebox/playlist=0/song=2");
+
+ // Inserting new song at 3rd position (aka as last element)
+ spyStrategy.dataPOST(ApiPath.parse("example-jukebox:jukebox/playlist=0/song=3"),
+ new JsonDataPostBody(stringInputStream("""
+ {
+ "id" = "C"
+ }""")), queryParams);
+
+ // Counting how many times we insert items in list
+ verify(spyTx, times(3)).replace(any(), any());
+ }
+
@Test
public void testPutReplaceListData() {
doReturn(immediateFluentFuture(Optional.of(mock(ContainerNode.class)))).when(netconfService)