a8ab07a82f2fc5b24b879cebcd235199cfcfab92
[netconf.git] / restconf / restconf-nb / src / test / java / org / opendaylight / restconf / nb / jaxrs / RestconfOperationsPostTest.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.restconf.nb.jaxrs;
9
10 import static org.junit.Assert.assertNull;
11 import static org.junit.jupiter.api.Assertions.assertEquals;
12 import static org.junit.jupiter.api.Assertions.assertSame;
13 import static org.mockito.ArgumentMatchers.any;
14 import static org.mockito.ArgumentMatchers.eq;
15 import static org.mockito.Mockito.doReturn;
16 import static org.mockito.Mockito.mock;
17
18 import com.google.common.util.concurrent.Futures;
19 import java.util.List;
20 import java.util.Optional;
21 import org.junit.jupiter.api.Test;
22 import org.junit.jupiter.api.extension.ExtendWith;
23 import org.mockito.Mock;
24 import org.mockito.junit.jupiter.MockitoExtension;
25 import org.opendaylight.mdsal.dom.api.DOMActionService;
26 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
27 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
28 import org.opendaylight.mdsal.dom.api.DOMNotificationService;
29 import org.opendaylight.mdsal.dom.api.DOMRpcImplementationNotAvailableException;
30 import org.opendaylight.mdsal.dom.api.DOMRpcResult;
31 import org.opendaylight.mdsal.dom.api.DOMRpcService;
32 import org.opendaylight.mdsal.dom.api.DOMSchemaService;
33 import org.opendaylight.mdsal.dom.spi.DefaultDOMRpcResult;
34 import org.opendaylight.mdsal.dom.spi.FixedDOMSchemaService;
35 import org.opendaylight.netconf.dom.api.NetconfDataTreeService;
36 import org.opendaylight.yangtools.yang.common.ErrorTag;
37 import org.opendaylight.yangtools.yang.common.ErrorType;
38 import org.opendaylight.yangtools.yang.common.QName;
39 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
40 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
41 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
42 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
43 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
44 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
45 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
46
47 @ExtendWith(MockitoExtension.class)
48 class RestconfOperationsPostTest extends AbstractRestconfTest {
49     private static final QName RPC = QName.create("invoke:rpc:module", "2013-12-03", "rpc-test");
50     private static final ContainerNode INPUT = Builders.containerBuilder()
51         .withNodeIdentifier(new NodeIdentifier(QName.create(RPC, "input")))
52         .withChild(Builders.containerBuilder()
53             .withNodeIdentifier(new NodeIdentifier(QName.create(RPC, "cont")))
54             .withChild(ImmutableNodes.leafNode(QName.create(RPC, "lf"), "test"))
55             .build())
56         .build();
57     private static final ContainerNode OUTPUT = Builders.containerBuilder()
58         .withNodeIdentifier(new NodeIdentifier(QName.create(RPC, "output")))
59         .withChild(ImmutableNodes.leafNode(QName.create(RPC, "content"), "operation result"))
60         .build();
61     private static final EffectiveModelContext MODEL_CONTEXT =
62         YangParserTestUtils.parseYangResourceDirectory("/invoke-rpc");
63
64     @Mock
65     private DOMNotificationService notificationService;
66
67     @Override
68     EffectiveModelContext modelContext() {
69         return MODEL_CONTEXT;
70     }
71
72     @Test
73     void testInvokeRpcWithNonEmptyOutput() {
74         final var result = mock(ContainerNode.class);
75         doReturn(false).when(result).isEmpty();
76
77         prepNNC(result);
78         assertSame(result, assertNormalizedNode(200, ar -> restconf.operationsXmlPOST(
79             apiPath("invoke-rpc-module:rpc-test"), stringInputStream("""
80                 <input xmlns="invoke:rpc:module"/>"""), uriInfo, ar)));
81     }
82
83     @Test
84     void testInvokeRpcWithEmptyOutput() {
85         final var result = mock(ContainerNode.class);
86         doReturn(true).when(result).isEmpty();
87
88         prepNNC(result);
89         assertNull(assertEntity(204, ar -> restconf.operationsJsonPOST(apiPath("invoke-rpc-module:rpc-test"),
90             stringInputStream("""
91                 {
92                   "invoke-rpc-module:input" : {
93                   }
94                 }"""), uriInfo, ar)));
95     }
96
97     @Test
98     void invokeRpcTest() {
99         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult(OUTPUT, List.of()))).when(rpcService)
100             .invokeRpc(RPC, INPUT);
101
102         assertEquals(OUTPUT, assertNormalizedNode(200, ar -> restconf.operationsXmlPOST(
103             apiPath("invoke-rpc-module:rpc-test"), stringInputStream("""
104                 <input xmlns="invoke:rpc:module">
105                   <cont>
106                     <lf>test</lf>
107                   </cont>
108                 </input>"""), uriInfo, ar)));
109     }
110
111     @Test
112     void invokeRpcErrorsAndCheckTestTest() throws Exception {
113         final var exception = new DOMRpcImplementationNotAvailableException(
114                 "No implementation of RPC " + RPC + " available.");
115         doReturn(Futures.immediateFailedFuture(exception)).when(rpcService).invokeRpc(RPC, INPUT);
116
117         final var error = assertError(ar -> restconf.operationsJsonPOST(apiPath("invoke-rpc-module:rpc-test"),
118             stringInputStream("""
119                 {
120                   "invoke-rpc-module:input" : {
121                     "cont" : {
122                       "lf" : "test"
123                     }
124                   }
125                 }"""), uriInfo, ar));
126         assertEquals("No implementation of RPC (invoke:rpc:module?revision=2013-12-03)rpc-test available.",
127             error.getErrorMessage());
128         assertEquals(ErrorType.RPC, error.getErrorType());
129         assertEquals(ErrorTag.OPERATION_FAILED, error.getErrorTag());
130     }
131
132     @Test
133     void invokeRpcViaMountPointTest() throws Exception {
134         doReturn(Optional.of(new FixedDOMSchemaService(MODEL_CONTEXT))).when(mountPoint)
135             .getService(DOMSchemaService.class);
136         doReturn(Optional.of(rpcService)).when(mountPoint).getService(DOMRpcService.class);
137         doReturn(Optional.empty()).when(mountPoint).getService(DOMActionService.class);
138         doReturn(Optional.empty()).when(mountPoint).getService(DOMMountPointService.class);
139         doReturn(Optional.empty()).when(mountPoint).getService(NetconfDataTreeService.class);
140         doReturn(Optional.of(dataBroker)).when(mountPoint).getService(DOMDataBroker.class);
141         doReturn(Optional.of(mountPoint)).when(mountPointService).getMountPoint(YangInstanceIdentifier.of(
142             QName.create("urn:ietf:params:xml:ns:yang:ietf-yang-library", "2019-01-04", "modules-state")));
143         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult(OUTPUT, List.of()))).when(rpcService)
144             .invokeRpc(RPC, INPUT);
145
146         assertEquals(OUTPUT, assertNormalizedNode(200,
147             ar -> restconf.operationsJsonPOST(
148                 apiPath("ietf-yang-library:modules-state/yang-ext:mount/invoke-rpc-module:rpc-test"),
149                 stringInputStream("""
150                     {
151                       "invoke-rpc-module:input" : {
152                         "cont" : {
153                           "lf" : "test"
154                         }
155                       }
156                     }"""), uriInfo, ar)));
157     }
158
159     @Test
160     void invokeRpcMissingMountPointServiceTest() {
161         doReturn(Optional.of(new FixedDOMSchemaService(MODEL_CONTEXT))).when(mountPoint)
162             .getService(DOMSchemaService.class);
163         doReturn(Optional.empty()).when(mountPoint).getService(DOMRpcService.class);
164         doReturn(Optional.empty()).when(mountPoint).getService(DOMActionService.class);
165         doReturn(Optional.empty()).when(mountPoint).getService(DOMMountPointService.class);
166         doReturn(Optional.empty()).when(mountPoint).getService(NetconfDataTreeService.class);
167         doReturn(Optional.of(dataBroker)).when(mountPoint).getService(DOMDataBroker.class);
168         doReturn(Optional.of(mountPoint)).when(mountPointService).getMountPoint(YangInstanceIdentifier.of(
169             QName.create("urn:ietf:params:xml:ns:yang:ietf-yang-library", "2019-01-04", "modules-state")));
170
171         final var error = assertError(
172             ar -> restconf.operationsJsonPOST(
173                 apiPath("ietf-yang-library:modules-state/yang-ext:mount/invoke-rpc-module:rpc-test"),
174                 stringInputStream("""
175                     {
176                       "invoke-rpc-module:input" : {
177                       }
178                     }"""), uriInfo, ar));
179         assertEquals("RPC invocation is not available", error.getErrorMessage());
180         assertEquals(ErrorType.PROTOCOL, error.getErrorType());
181         assertEquals(ErrorTag.OPERATION_NOT_SUPPORTED, error.getErrorTag());
182     }
183
184     @Test
185     void checkResponseTest() throws Exception {
186         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult(OUTPUT, List.of())))
187             .when(rpcService).invokeRpc(RPC, INPUT);
188
189         assertEquals(OUTPUT, assertNormalizedNode(200, ar -> restconf.operationsJsonPOST(
190             apiPath("invoke-rpc-module:rpc-test"),
191             stringInputStream("""
192                 {
193                   "invoke-rpc-module:input" : {
194                     "cont" : {
195                       "lf" : "test"
196                     }
197                   }
198                 }"""), uriInfo, ar)));
199     }
200
201     private void prepNNC(final ContainerNode result) {
202         final var qname = QName.create("invoke:rpc:module", "2013-12-03", "rpc-test");
203         final var domRpcResult = mock(DOMRpcResult.class);
204         doReturn(Futures.immediateFuture(domRpcResult)).when(rpcService).invokeRpc(eq(qname), any(ContainerNode.class));
205         doReturn(result).when(domRpcResult).value();
206     }
207 }