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