2 * Copyright (c) 2023 PANTHEON.tech, s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.restconf.nb.jaxrs;
10 import static org.junit.jupiter.api.Assertions.assertNull;
11 import static org.mockito.ArgumentMatchers.any;
12 import static org.mockito.ArgumentMatchers.eq;
13 import static org.mockito.Mockito.doNothing;
14 import static org.mockito.Mockito.doReturn;
15 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFalseFluentFuture;
16 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFluentFuture;
17 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateTrueFluentFuture;
19 import java.util.List;
20 import java.util.Optional;
21 import javax.ws.rs.core.MultivaluedHashMap;
22 import javax.ws.rs.core.MultivaluedMap;
23 import org.junit.jupiter.api.BeforeEach;
24 import org.junit.jupiter.api.Test;
25 import org.junit.jupiter.api.extension.ExtendWith;
26 import org.mockito.Mock;
27 import org.mockito.junit.jupiter.MockitoExtension;
28 import org.opendaylight.mdsal.common.api.CommitInfo;
29 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
30 import org.opendaylight.mdsal.dom.api.DOMActionService;
31 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
32 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
33 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
34 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
35 import org.opendaylight.mdsal.dom.api.DOMRpcService;
36 import org.opendaylight.mdsal.dom.api.DOMSchemaService;
37 import org.opendaylight.mdsal.dom.spi.FixedDOMSchemaService;
38 import org.opendaylight.netconf.dom.api.NetconfDataTreeService;
39 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
41 @ExtendWith(MockitoExtension.class)
42 class RestconfDataPutTest extends AbstractRestconfTest {
43 private final MultivaluedMap<String, String> queryParamenters = new MultivaluedHashMap<>();
46 private DOMDataTreeReadTransaction readTx;
48 private DOMDataTreeReadWriteTransaction rwTx;
52 doReturn(readTx).when(dataBroker).newReadOnlyTransaction();
53 doReturn(rwTx).when(dataBroker).newReadWriteTransaction();
54 doReturn(CommitInfo.emptyFluentFuture()).when(rwTx).commit();
59 doReturn(queryParamenters).when(uriInfo).getQueryParameters();
60 doReturn(immediateTrueFluentFuture()).when(readTx).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
61 doNothing().when(rwTx).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX);
63 assertNull(assertEntity(204, ar -> restconf.dataJsonPUT(JUKEBOX_API_PATH, uriInfo, stringInputStream("""
65 "example-jukebox:jukebox" : {
74 void testPutDataWithMountPoint() {
75 doReturn(queryParamenters).when(uriInfo).getQueryParameters();
76 doReturn(immediateTrueFluentFuture()).when(readTx).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
77 doNothing().when(rwTx).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX);
78 doReturn(Optional.of(mountPoint)).when(mountPointService).getMountPoint(any());
79 doReturn(Optional.of(new FixedDOMSchemaService(JUKEBOX_SCHEMA))).when(mountPoint)
80 .getService(DOMSchemaService.class);
81 doReturn(Optional.of(dataBroker)).when(mountPoint).getService(DOMDataBroker.class);
82 doReturn(Optional.of(rpcService)).when(mountPoint).getService(DOMRpcService.class);
83 doReturn(Optional.empty()).when(mountPoint).getService(DOMActionService.class);
84 doReturn(Optional.empty()).when(mountPoint).getService(DOMMountPointService.class);
85 doReturn(Optional.empty()).when(mountPoint).getService(NetconfDataTreeService.class);
87 assertNull(assertEntity(204, ar -> restconf.dataXmlPUT(
88 apiPath("example-jukebox:jukebox/yang-ext:mount/example-jukebox:jukebox"), uriInfo,
90 <jukebox xmlns="http://example.com/ns/example-jukebox">
94 </jukebox>"""), ar)));
98 public void testPutDataWithInsertLast() {
99 // Mocking the query parameters to include 'insert=last'
100 final var queryParams = new MultivaluedHashMap<String, String>();
101 queryParams.put("insert", List.of("last"));
102 doReturn(queryParams).when(uriInfo).getQueryParameters();
104 doReturn(immediateFalseFluentFuture()).when(readTx)
105 .exists(eq(LogicalDatastoreType.CONFIGURATION), any(YangInstanceIdentifier.class));
107 assertNull(assertEntity(201, ar -> restconf.dataJsonPUT(
108 apiPath("example-jukebox:jukebox/playlist=0/song=3"), uriInfo, stringInputStream("""
110 "example-jukebox:song" : [
119 public void testPutDataWithInsertFirst() {
120 // Mocking the query parameters to include 'insert=first'
121 final var queryParams = new MultivaluedHashMap<String, String>();
122 queryParams.put("insert", List.of("first"));
123 doReturn(queryParams).when(uriInfo).getQueryParameters();
125 doReturn(immediateFalseFluentFuture()).when(readTx)
126 .exists(eq(LogicalDatastoreType.CONFIGURATION), any(YangInstanceIdentifier.class));
127 // Mocking existed playlist with two songs in DS
128 doReturn(immediateFluentFuture(Optional.of(PLAYLIST_WITH_SONGS))).when(rwTx)
129 .read(eq(LogicalDatastoreType.CONFIGURATION), any(YangInstanceIdentifier.class));
131 assertNull(assertEntity(201, ar -> restconf.dataJsonPUT(
132 apiPath("example-jukebox:jukebox/playlist=0/song=3"), uriInfo, stringInputStream("""
134 "example-jukebox:song" : [
143 public void testPutDataWithInsertBefore() {
144 // Mocking the query parameters to include 'insert=before' and 'point=example-jukebox:jukebox/playlist=0/song=2'
145 final var queryParams = new MultivaluedHashMap<String, String>();
146 queryParams.put("insert", List.of("before"));
147 queryParams.put("point", List.of("example-jukebox:jukebox/playlist=0/song=2"));
148 doReturn(queryParams).when(uriInfo).getQueryParameters();
150 doReturn(immediateFalseFluentFuture()).when(readTx)
151 .exists(eq(LogicalDatastoreType.CONFIGURATION), any(YangInstanceIdentifier.class));
152 // Mocking existed playlist with two songs in DS
153 doReturn(immediateFluentFuture(Optional.of(PLAYLIST_WITH_SONGS))).when(rwTx)
154 .read(eq(LogicalDatastoreType.CONFIGURATION), any(YangInstanceIdentifier.class));
156 assertNull(assertEntity(201, ar -> restconf.dataJsonPUT(
157 apiPath("example-jukebox:jukebox/playlist=0/song=3"), uriInfo, stringInputStream("""
159 "example-jukebox:song" : [
169 public void testPutDataWithInsertAfter() {
170 // Mocking the query parameters to include 'insert=after' and 'point=example-jukebox:jukebox/playlist=0/song=1'
171 final var queryParams = new MultivaluedHashMap<String, String>();
172 queryParams.put("insert", List.of("after"));
173 queryParams.put("point", List.of("example-jukebox:jukebox/playlist=0/song=1"));
174 doReturn(queryParams).when(uriInfo).getQueryParameters();
176 doReturn(immediateFalseFluentFuture()).when(readTx)
177 .exists(eq(LogicalDatastoreType.CONFIGURATION), any(YangInstanceIdentifier.class));
178 doReturn(immediateFluentFuture(Optional.of(PLAYLIST_WITH_SONGS))).when(rwTx)
179 .read(eq(LogicalDatastoreType.CONFIGURATION), any(YangInstanceIdentifier.class));
181 assertNull(assertEntity(201, ar -> restconf.dataJsonPUT(
182 apiPath("example-jukebox:jukebox/playlist=0/song=3"), uriInfo, stringInputStream("""
184 "example-jukebox:song" : [