Merge "Switch initial config files format to xml and add autodetect adapter for confi...
[controller.git] / opendaylight / md-sal / sal-rest-connector / src / test / java / org / opendaylight / controller / sal / restconf / impl / test / RestPostOperationTest.java
1 package org.opendaylight.controller.sal.restconf.impl.test;
2
3 import static org.junit.Assert.assertEquals;
4 import static org.mockito.Matchers.any;
5 import static org.mockito.Mockito.mock;
6 import static org.mockito.Mockito.when;
7 import static org.opendaylight.controller.sal.restconf.impl.test.RestOperationUtils.JSON;
8 import static org.opendaylight.controller.sal.restconf.impl.test.RestOperationUtils.XML;
9 import static org.opendaylight.controller.sal.restconf.impl.test.RestOperationUtils.createUri;
10 import static org.opendaylight.controller.sal.restconf.impl.test.RestOperationUtils.entity;
11
12 import java.io.FileNotFoundException;
13 import java.io.IOException;
14 import java.io.InputStream;
15 import java.io.UnsupportedEncodingException;
16 import java.net.URI;
17 import java.net.URISyntaxException;
18 import java.util.concurrent.Future;
19 import java.util.logging.Level;
20
21 import javax.ws.rs.client.Entity;
22 import javax.ws.rs.core.Application;
23 import javax.ws.rs.core.MediaType;
24 import javax.ws.rs.core.Response;
25
26 import org.glassfish.jersey.server.ResourceConfig;
27 import org.glassfish.jersey.test.JerseyTest;
28 import org.glassfish.jersey.test.TestProperties;
29 import org.junit.Before;
30 import org.junit.BeforeClass;
31 import org.junit.Test;
32 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
33 import org.opendaylight.controller.sal.core.api.mount.MountService;
34 import org.opendaylight.controller.sal.rest.api.Draft01;
35 import org.opendaylight.controller.sal.rest.api.Draft02;
36 import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider;
37 import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
38 import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider;
39 import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
40 import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
41 import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
42 import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
43 import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
44 import org.opendaylight.yangtools.yang.common.QName;
45 import org.opendaylight.yangtools.yang.common.RpcResult;
46 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
47 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
48 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
49
50 public class RestPostOperationTest extends JerseyTest {
51
52     private static String xmlData;
53     private static String xmlDataAbsolutePath;
54     private static String jsonData;
55     private static String jsonDataAbsolutePath;
56     private static String xmlDataRpcInput;
57     private static CompositeNodeWrapper cnSnDataOutput;
58     private static String jsonDataRpcInput;
59     private static String xmlData2;
60
61     private static ControllerContext controllerContext;
62     private static BrokerFacade brokerFacade;
63     private static RestconfImpl restconfImpl;
64     private static SchemaContext schemaContextYangsIetf;
65     private static SchemaContext schemaContextTestModule;
66
67     @BeforeClass
68     public static void init() throws URISyntaxException, IOException {
69         schemaContextYangsIetf = TestUtils.loadSchemaContext("/full-versions/yangs");
70         schemaContextTestModule = TestUtils.loadSchemaContext("/full-versions/test-module");
71         controllerContext = ControllerContext.getInstance();
72         brokerFacade = mock(BrokerFacade.class);
73         restconfImpl = RestconfImpl.getInstance();
74         restconfImpl.setBroker(brokerFacade);
75         restconfImpl.setControllerContext(controllerContext);
76         loadData();
77     }
78
79     @Before
80     public void logs() throws IOException, URISyntaxException {
81         /* enable/disable Jersey logs to console */
82         /*
83          * List<LogRecord> loggedRecords = getLoggedRecords(); for (LogRecord l
84          * : loggedRecords) { System.out.println(l.getMessage()); }
85          */
86     }
87
88     @Override
89     protected Application configure() {
90         /* enable/disable Jersey logs to console */
91
92         /*
93          * enable(TestProperties.LOG_TRAFFIC);
94          */
95         enable(TestProperties.DUMP_ENTITY);
96         enable(TestProperties.RECORD_LOG_LEVEL);
97         set(TestProperties.RECORD_LOG_LEVEL, Level.ALL.intValue());
98
99         ResourceConfig resourceConfig = new ResourceConfig();
100         resourceConfig = resourceConfig.registerInstances(restconfImpl, StructuredDataToXmlProvider.INSTANCE,
101                 StructuredDataToJsonProvider.INSTANCE, XmlToCompositeNodeProvider.INSTANCE,
102                 JsonToCompositeNodeProvider.INSTANCE);
103         return resourceConfig;
104     }
105
106     @Test
107     public void postOperationsDataViaUrl200() throws URISyntaxException, IOException {
108         controllerContext.setSchemas(schemaContextTestModule);
109         postOperationsDataViaUrl(Draft02.MediaTypes.DATA + JSON, cnSnDataOutput, jsonDataRpcInput, 200);
110         postOperationsDataViaUrl(Draft01.MediaTypes.DATA + JSON, cnSnDataOutput, jsonDataRpcInput, 200);
111         postOperationsDataViaUrl(MediaType.APPLICATION_JSON, cnSnDataOutput, jsonDataRpcInput, 200);
112
113         postOperationsDataViaUrl(Draft01.MediaTypes.DATA + XML, cnSnDataOutput, xmlDataRpcInput, 200);
114         postOperationsDataViaUrl(Draft02.MediaTypes.DATA + XML, cnSnDataOutput, xmlDataRpcInput, 200);
115         postOperationsDataViaUrl(MediaType.APPLICATION_XML, cnSnDataOutput, xmlDataRpcInput, 200);
116         postOperationsDataViaUrl(MediaType.TEXT_XML, cnSnDataOutput, xmlDataRpcInput, 200);
117     }
118
119     @Test
120     public void postOperationsDataViaUrl204() throws URISyntaxException, IOException {
121         controllerContext.setSchemas(schemaContextTestModule);
122         postOperationsDataViaUrl(Draft02.MediaTypes.DATA + JSON, cnSnDataOutput, jsonDataRpcInput, 204);
123         postOperationsDataViaUrl(Draft01.MediaTypes.DATA + JSON, cnSnDataOutput, jsonDataRpcInput, 204);
124         postOperationsDataViaUrl(MediaType.APPLICATION_JSON, cnSnDataOutput, jsonDataRpcInput, 204);
125
126         postOperationsDataViaUrl(Draft01.MediaTypes.DATA + XML, cnSnDataOutput, xmlDataRpcInput, 204);
127         postOperationsDataViaUrl(Draft02.MediaTypes.DATA + XML, cnSnDataOutput, xmlDataRpcInput, 204);
128         postOperationsDataViaUrl(MediaType.APPLICATION_XML, cnSnDataOutput, xmlDataRpcInput, 204);
129         postOperationsDataViaUrl(MediaType.TEXT_XML, cnSnDataOutput, xmlDataRpcInput, 204);
130     }
131
132     @Test
133     public void postOperationsDataViaUrl500() throws URISyntaxException, IOException {
134         controllerContext.setSchemas(schemaContextTestModule);
135         postOperationsDataViaUrl(Draft02.MediaTypes.DATA + JSON, cnSnDataOutput, jsonDataRpcInput, 500);
136         postOperationsDataViaUrl(Draft01.MediaTypes.DATA + JSON, cnSnDataOutput, jsonDataRpcInput, 500);
137         postOperationsDataViaUrl(MediaType.APPLICATION_JSON, cnSnDataOutput, jsonDataRpcInput, 500);
138
139         postOperationsDataViaUrl(Draft01.MediaTypes.DATA + XML, cnSnDataOutput, xmlDataRpcInput, 500);
140         postOperationsDataViaUrl(Draft02.MediaTypes.DATA + XML, cnSnDataOutput, xmlDataRpcInput, 500);
141         postOperationsDataViaUrl(MediaType.APPLICATION_XML, cnSnDataOutput, xmlDataRpcInput, 500);
142         postOperationsDataViaUrl(MediaType.TEXT_XML, cnSnDataOutput, xmlDataRpcInput, 500);
143     }
144
145     @Test
146     public void postOperationsDataViaUrl400() throws URISyntaxException, IOException {
147         controllerContext.setSchemas(schemaContextTestModule);
148         postOperationsDataViaUrl(Draft02.MediaTypes.DATA + JSON, cnSnDataOutput, jsonDataRpcInput, 400);
149         postOperationsDataViaUrl(Draft01.MediaTypes.DATA + JSON, cnSnDataOutput, jsonDataRpcInput, 400);
150         postOperationsDataViaUrl(MediaType.APPLICATION_JSON, cnSnDataOutput, jsonDataRpcInput, 400);
151
152         postOperationsDataViaUrl(Draft01.MediaTypes.DATA + XML, cnSnDataOutput, xmlDataRpcInput, 400);
153         postOperationsDataViaUrl(Draft02.MediaTypes.DATA + XML, cnSnDataOutput, xmlDataRpcInput, 400);
154         postOperationsDataViaUrl(MediaType.APPLICATION_XML, cnSnDataOutput, xmlDataRpcInput, 400);
155         postOperationsDataViaUrl(MediaType.TEXT_XML, cnSnDataOutput, xmlDataRpcInput, 400);
156     }
157
158     @Test
159     public void postOperationsDataViaUrl404() throws URISyntaxException, IOException {
160         controllerContext.setSchemas(schemaContextTestModule);
161         postOperationsDataViaUrl(Draft02.MediaTypes.DATA + JSON, cnSnDataOutput, jsonDataRpcInput, 404);
162         postOperationsDataViaUrl(Draft01.MediaTypes.DATA + JSON, cnSnDataOutput, jsonDataRpcInput, 404);
163         postOperationsDataViaUrl(MediaType.APPLICATION_JSON, cnSnDataOutput, jsonDataRpcInput, 404);
164
165         postOperationsDataViaUrl(Draft01.MediaTypes.DATA + XML, cnSnDataOutput, xmlDataRpcInput, 404);
166         postOperationsDataViaUrl(Draft02.MediaTypes.DATA + XML, cnSnDataOutput, xmlDataRpcInput, 404);
167         postOperationsDataViaUrl(MediaType.APPLICATION_XML, cnSnDataOutput, xmlDataRpcInput, 404);
168         postOperationsDataViaUrl(MediaType.TEXT_XML, cnSnDataOutput, xmlDataRpcInput, 404);
169     }
170
171     @Test
172     public void postConfigDataViaUrlConfigOnlyTest204() throws UnsupportedEncodingException, FileNotFoundException {
173         controllerContext.setSchemas(schemaContextYangsIetf);
174         mockCommitConfigurationDataPostMethod(TransactionStatus.COMMITED);
175         postDataViaUrlTest("/config", "", Draft02.MediaTypes.DATA + JSON, jsonDataAbsolutePath, 204);
176         postDataViaUrlTest("/config", "", Draft02.MediaTypes.DATA + XML, xmlDataAbsolutePath, 204);
177         postDataViaUrlTest("/config", "", MediaType.APPLICATION_JSON, jsonDataAbsolutePath, 204);
178         postDataViaUrlTest("/config", "", MediaType.APPLICATION_XML, xmlDataAbsolutePath, 204);
179         postDataViaUrlTest("/config", "", MediaType.TEXT_XML, xmlDataAbsolutePath, 204);
180     }
181
182     @Test
183     public void postConfigDataViaUrlConfigOnlyTest202() throws UnsupportedEncodingException, FileNotFoundException {
184         controllerContext.setSchemas(schemaContextYangsIetf);
185         mockCommitConfigurationDataPostMethod(null);
186         postDataViaUrlTest("/config", "", Draft02.MediaTypes.DATA + JSON, jsonDataAbsolutePath, 202);
187         postDataViaUrlTest("/config", "", Draft02.MediaTypes.DATA + XML, xmlDataAbsolutePath, 202);
188         postDataViaUrlTest("/config", "", MediaType.APPLICATION_JSON, jsonDataAbsolutePath, 202);
189         postDataViaUrlTest("/config", "", MediaType.APPLICATION_XML, xmlDataAbsolutePath, 202);
190         postDataViaUrlTest("/config", "", MediaType.TEXT_XML, xmlDataAbsolutePath, 202);
191     }
192
193     @Test
194     public void postConfigDataViaUrlConfigOnlyTest500() throws UnsupportedEncodingException, FileNotFoundException {
195         controllerContext.setSchemas(schemaContextYangsIetf);
196         mockCommitConfigurationDataPostMethod(TransactionStatus.FAILED);
197         postDataViaUrlTest("/config", "", Draft02.MediaTypes.DATA + JSON, jsonDataAbsolutePath, 500);
198         postDataViaUrlTest("/config", "", Draft02.MediaTypes.DATA + XML, xmlDataAbsolutePath, 500);
199         postDataViaUrlTest("/config", "", MediaType.APPLICATION_JSON, jsonDataAbsolutePath, 500);
200         postDataViaUrlTest("/config", "", MediaType.APPLICATION_XML, xmlDataAbsolutePath, 500);
201         postDataViaUrlTest("/config", "", MediaType.TEXT_XML, xmlDataAbsolutePath, 500);
202     }
203
204     @Test
205     public void postConfigDataViaUrlTest204() throws UnsupportedEncodingException {
206         controllerContext.setSchemas(schemaContextYangsIetf);
207         mockCommitConfigurationDataPostMethod(TransactionStatus.COMMITED);
208         String urlPath = "ietf-interfaces:interfaces";
209         postDataViaUrlTest("/config/", urlPath, Draft02.MediaTypes.DATA + JSON, jsonData, 204);
210         postDataViaUrlTest("/config/", urlPath, Draft02.MediaTypes.DATA + XML, xmlData, 204);
211         postDataViaUrlTest("/config/", urlPath, MediaType.APPLICATION_JSON, jsonData, 204);
212         postDataViaUrlTest("/config/", urlPath, MediaType.APPLICATION_XML, xmlData, 204);
213         postDataViaUrlTest("/config/", urlPath, MediaType.TEXT_XML, xmlData, 204);
214     }
215
216     @Test
217     public void postConfigDataViaUrlTest202() throws UnsupportedEncodingException {
218         controllerContext.setSchemas(schemaContextYangsIetf);
219         mockCommitConfigurationDataPostMethod(null);
220         String urlPath = "ietf-interfaces:interfaces";
221         postDataViaUrlTest("/config/", urlPath, Draft02.MediaTypes.DATA + JSON, jsonData, 202);
222         postDataViaUrlTest("/config/", urlPath, Draft02.MediaTypes.DATA + XML, xmlData, 202);
223         postDataViaUrlTest("/config/", urlPath, MediaType.APPLICATION_JSON, jsonData, 202);
224         postDataViaUrlTest("/config/", urlPath, MediaType.APPLICATION_XML, xmlData, 202);
225         postDataViaUrlTest("/config/", urlPath, MediaType.TEXT_XML, xmlData, 202);
226     }
227
228     @Test
229     public void postConfigDataViaUrlTest500() throws UnsupportedEncodingException {
230         controllerContext.setSchemas(schemaContextYangsIetf);
231         mockCommitConfigurationDataPostMethod(TransactionStatus.FAILED);
232         String urlPath = "ietf-interfaces:interfaces";
233         postDataViaUrlTest("/config/", urlPath, Draft02.MediaTypes.DATA + JSON, jsonData, 500);
234         postDataViaUrlTest("/config/", urlPath, Draft02.MediaTypes.DATA + XML, xmlData, 500);
235         postDataViaUrlTest("/config/", urlPath, MediaType.APPLICATION_JSON, jsonData, 500);
236         postDataViaUrlTest("/config/", urlPath, MediaType.APPLICATION_XML, xmlData, 500);
237         postDataViaUrlTest("/config/", urlPath, MediaType.TEXT_XML, xmlData, 500);
238     }
239
240     @Test
241     public void postDatastoreDataViaUrlTest204() throws UnsupportedEncodingException {
242         controllerContext.setSchemas(schemaContextYangsIetf);
243         mockCommitConfigurationDataPostMethod(TransactionStatus.COMMITED);
244         String urlPath = "ietf-interfaces:interfaces";
245         postDataViaUrlTest("/datastore/", urlPath, Draft01.MediaTypes.DATA + JSON, jsonData, 204);
246         postDataViaUrlTest("/datastore/", urlPath, Draft01.MediaTypes.DATA + XML, xmlData, 204);
247         postDataViaUrlTest("/datastore/", urlPath, MediaType.APPLICATION_JSON, jsonData, 204);
248         postDataViaUrlTest("/datastore/", urlPath, MediaType.APPLICATION_XML, xmlData, 204);
249         postDataViaUrlTest("/datastore/", urlPath, MediaType.TEXT_XML, xmlData, 204);
250     }
251
252     @Test
253     public void postDatastoreDataViaUrlTest202() throws UnsupportedEncodingException {
254         controllerContext.setSchemas(schemaContextYangsIetf);
255         mockCommitConfigurationDataPostMethod(null);
256         String urlPath = "ietf-interfaces:interfaces";
257         postDataViaUrlTest("/datastore/", urlPath, Draft01.MediaTypes.DATA + JSON, jsonData, 202);
258         postDataViaUrlTest("/datastore/", urlPath, Draft01.MediaTypes.DATA + XML, xmlData, 202);
259         postDataViaUrlTest("/datastore/", urlPath, MediaType.APPLICATION_JSON, jsonData, 202);
260         postDataViaUrlTest("/datastore/", urlPath, MediaType.APPLICATION_XML, xmlData, 202);
261         postDataViaUrlTest("/datastore/", urlPath, MediaType.TEXT_XML, xmlData, 202);
262     }
263
264     @Test
265     public void postDatastoreDataViaUrlTest500() throws UnsupportedEncodingException {
266         controllerContext.setSchemas(schemaContextYangsIetf);
267         mockCommitConfigurationDataPostMethod(TransactionStatus.FAILED);
268         String urlPath = "ietf-interfaces:interfaces";
269         postDataViaUrlTest("/datastore/", urlPath, Draft01.MediaTypes.DATA + JSON, jsonData, 500);
270         postDataViaUrlTest("/datastore/", urlPath, Draft01.MediaTypes.DATA + XML, xmlData, 500);
271         postDataViaUrlTest("/datastore/", urlPath, MediaType.APPLICATION_JSON, jsonData, 500);
272         postDataViaUrlTest("/datastore/", urlPath, MediaType.APPLICATION_XML, xmlData, 500);
273         postDataViaUrlTest("/datastore/", urlPath, MediaType.TEXT_XML, xmlData, 500);
274     }
275
276     @Test
277     public void postDataViaUrlMountPoint() throws UnsupportedEncodingException {
278         controllerContext.setSchemas(schemaContextYangsIetf);
279         mockCommitConfigurationDataPostMethod(TransactionStatus.COMMITED);
280
281         MountService mockMountService = mock(MountService.class);
282         SchemaContext otherSchemaContext = schemaContextTestModule;
283         when(mockMountService.getMountPoint(any(InstanceIdentifier.class))).thenReturn(
284                 new DummyMountInstanceImpl.Builder().setSchemaContext(otherSchemaContext).build());
285
286         ControllerContext.getInstance().setMountService(mockMountService);
287
288         String uri = createUri("/config/", "ietf-interfaces:interfaces/interface/0/test-module:cont/cont1");
289         Response response = target(uri).request(Draft02.MediaTypes.DATA + XML).post(
290                 entity(xmlData2, Draft02.MediaTypes.DATA + XML));
291         // 204 code is returned when COMMITED transaction status is put as input
292         // to mock method
293         assertEquals(204, response.getStatus());
294     }
295
296     private void postDataViaUrlTest(String urlPrefix, String urlPath, String mediaType, String data, int responseStatus)
297             throws UnsupportedEncodingException {
298         String url = createUri(urlPrefix, urlPath);
299         Response response = target(url).request(mediaType).post(entity(data, mediaType));
300         assertEquals(responseStatus, response.getStatus());
301     }
302
303     private void mockCommitConfigurationDataPostMethod(TransactionStatus statusName) {
304         RpcResult<TransactionStatus> rpcResult = new DummyRpcResult.Builder<TransactionStatus>().result(statusName)
305                 .build();
306         Future<RpcResult<TransactionStatus>> dummyFuture = null;
307         if (statusName != null) {
308             dummyFuture = DummyFuture.builder().rpcResult(rpcResult).build();
309         } else {
310             dummyFuture = DummyFuture.builder().build();
311         }
312
313         when(brokerFacade.commitConfigurationDataPost(any(InstanceIdentifier.class), any(CompositeNode.class)))
314                 .thenReturn(dummyFuture);
315     }
316
317     private static CompositeNodeWrapper prepareCnSnRpcOutput() throws URISyntaxException {
318         CompositeNodeWrapper cnSnDataOutput = new CompositeNodeWrapper(new URI("test:module"), "output");
319         CompositeNodeWrapper cont = new CompositeNodeWrapper(new URI("test:module"), "cont-output");
320         cnSnDataOutput.addValue(cont);
321         cnSnDataOutput.unwrap();
322         return cnSnDataOutput;
323     }
324
325     private void mockInvokeRpc(CompositeNode compositeNode, boolean sucessful) {
326         RpcResult<CompositeNode> rpcResult = new DummyRpcResult.Builder<CompositeNode>().result(compositeNode)
327                 .isSuccessful(sucessful).build();
328         when(brokerFacade.invokeRpc(any(QName.class), any(CompositeNode.class))).thenReturn(rpcResult);
329     }
330
331     private void postOperationsDataViaUrl(String mediaType, CompositeNode cnSnDataOut, String dataIn, int statusCode)
332             throws FileNotFoundException, UnsupportedEncodingException {
333         String url = createUri("/operations/", "test-module:rpc-test");
334         Response response = null;
335         switch (statusCode) {
336         case 200:
337             mockInvokeRpc(cnSnDataOut, true);
338             break;
339         case 204:
340             mockInvokeRpc(null, true);
341             break;
342         case 500:
343             mockInvokeRpc(null, false);
344             break;
345         case 400:
346             response = target(url).request(mediaType).post(Entity.entity("{}", mediaType));
347             break;
348         case 404:
349             url = createUri("/operations/", "test-module:rpc-wrongtest");
350             break;
351         }
352         response = response == null ? target(url).request(mediaType).post(Entity.entity(dataIn, mediaType)) : response;
353         assertEquals(statusCode, response.getStatus());
354     }
355
356     private static void loadData() throws IOException, URISyntaxException {
357
358         InputStream xmlStream = RestconfImplTest.class.getResourceAsStream("/parts/ietf-interfaces_interfaces.xml");
359         xmlData = TestUtils.getDocumentInPrintableForm(TestUtils.loadDocumentFrom(xmlStream));
360
361         xmlStream = RestconfImplTest.class.getResourceAsStream("/parts/ietf-interfaces_interfaces_absolute_path.xml");
362         xmlDataAbsolutePath = TestUtils.getDocumentInPrintableForm(TestUtils.loadDocumentFrom(xmlStream));
363
364         String jsonPath = RestconfImplTest.class.getResource("/parts/ietf-interfaces_interfaces.json").getPath();
365         jsonData = TestUtils.loadTextFile(jsonPath);
366
367         String jsonFullPath = RestconfImplTest.class
368                 .getResource("/parts/ietf-interfaces_interfaces_absolute_path.json").getPath();
369         jsonDataAbsolutePath = TestUtils.loadTextFile(jsonFullPath);
370
371         String xmlPathRpcInput = RestconfImplTest.class.getResource("/full-versions/test-data2/data-rpc-input.xml")
372                 .getPath();
373         xmlDataRpcInput = TestUtils.loadTextFile(xmlPathRpcInput);
374         cnSnDataOutput = prepareCnSnRpcOutput();
375
376         String jsonPathToRpcInput = RestconfImplTest.class.getResource("/full-versions/test-data2/data-rpc-input.json")
377                 .getPath();
378         jsonDataRpcInput = TestUtils.loadTextFile(jsonPathToRpcInput);
379
380         String data2Input = RestconfImplTest.class.getResource("/full-versions/test-data2/data2.xml").getPath();
381         xmlData2 = TestUtils.loadTextFile(data2Input);
382
383     }
384 }