Take advantage of MultipartTransactionAware
[controller.git] / opendaylight / md-sal / sal-rest-connector / src / test / java / org / opendaylight / controller / sal / restconf / impl / test / RestGetOperationTest.java
1 /*
2  * Copyright (c) 2014 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.controller.sal.restconf.impl.test;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertTrue;
12 import static org.mockito.Matchers.any;
13 import static org.mockito.Mockito.mock;
14 import static org.mockito.Mockito.when;
15
16 import java.io.FileNotFoundException;
17 import java.io.UnsupportedEncodingException;
18 import java.net.URI;
19 import java.net.URISyntaxException;
20 import java.util.ArrayList;
21 import java.util.List;
22 import java.util.regex.Matcher;
23 import java.util.regex.Pattern;
24
25 import javax.ws.rs.core.Application;
26 import javax.ws.rs.core.MediaType;
27 import javax.ws.rs.core.Response;
28
29 import org.glassfish.jersey.server.ResourceConfig;
30 import org.glassfish.jersey.test.JerseyTest;
31 import org.junit.BeforeClass;
32 import org.junit.Test;
33 import org.opendaylight.controller.sal.core.api.mount.MountInstance;
34 import org.opendaylight.controller.sal.core.api.mount.MountService;
35 import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider;
36 import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
37 import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider;
38 import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
39 import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
40 import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
41 import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
42 import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
43 import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
44 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
45 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
46 import org.opendaylight.yangtools.yang.data.api.Node;
47 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
48
49 public class RestGetOperationTest extends JerseyTest {
50
51     private static BrokerFacade brokerFacade;
52     private static RestconfImpl restconfImpl;
53     private static SchemaContext schemaContextYangsIetf;
54     private static SchemaContext schemaContextTestModule;
55     private static CompositeNode answerFromGet;
56
57     private static SchemaContext schemaContextModules;
58     private static SchemaContext schemaContextBehindMountPoint;
59
60     @BeforeClass
61     public static void init() throws FileNotFoundException {
62         schemaContextYangsIetf = TestUtils.loadSchemaContext("/full-versions/yangs");
63         schemaContextTestModule = TestUtils.loadSchemaContext("/full-versions/test-module");
64         ControllerContext controllerContext = ControllerContext.getInstance();
65         controllerContext.setSchemas(schemaContextYangsIetf);
66         brokerFacade = mock(BrokerFacade.class);
67         restconfImpl = RestconfImpl.getInstance();
68         restconfImpl.setBroker(brokerFacade);
69         restconfImpl.setControllerContext(controllerContext);
70         answerFromGet = prepareCompositeNodeWithIetfInterfacesInterfacesData();
71
72         schemaContextModules = TestUtils.loadSchemaContext("/modules");
73         schemaContextBehindMountPoint = TestUtils.loadSchemaContext("/modules/modules-behind-mount-point");
74     }
75
76     @Override
77     protected Application configure() {
78         /* enable/disable Jersey logs to console */
79         // enable(TestProperties.LOG_TRAFFIC);
80         // enable(TestProperties.DUMP_ENTITY);
81         // enable(TestProperties.RECORD_LOG_LEVEL);
82         // set(TestProperties.RECORD_LOG_LEVEL, Level.ALL.intValue());
83         ResourceConfig resourceConfig = new ResourceConfig();
84         resourceConfig = resourceConfig.registerInstances(restconfImpl, StructuredDataToXmlProvider.INSTANCE,
85                 StructuredDataToJsonProvider.INSTANCE, XmlToCompositeNodeProvider.INSTANCE,
86                 JsonToCompositeNodeProvider.INSTANCE);
87         return resourceConfig;
88     }
89
90     /**
91      * Tests of status codes for "/operational/{identifier}".
92      */
93     @Test
94     public void getOperationalStatusCodes() throws UnsupportedEncodingException {
95         mockReadOperationalDataMethod();
96         String uri = "/operational/ietf-interfaces:interfaces/interface/eth0";
97         assertEquals(200, get(uri, MediaType.APPLICATION_XML));
98
99         uri = "/operational/wrong-module:interfaces/interface/eth0";
100         assertEquals(400, get(uri, MediaType.APPLICATION_XML));
101     }
102
103     /**
104      * Tests of status codes for "/config/{identifier}".
105      */
106     @Test
107     public void getConfigStatusCodes() throws UnsupportedEncodingException {
108         mockReadConfigurationDataMethod();
109         String uri = "/config/ietf-interfaces:interfaces/interface/eth0";
110         assertEquals(200, get(uri, MediaType.APPLICATION_XML));
111
112         uri = "/config/wrong-module:interfaces/interface/eth0";
113         assertEquals(400, get(uri, MediaType.APPLICATION_XML));
114     }
115
116     /**
117      * MountPoint test. URI represents mount point.
118      */
119     @Test
120     public void getDataWithUrlMountPoint() throws UnsupportedEncodingException, URISyntaxException {
121         when(
122                 brokerFacade.readConfigurationDataBehindMountPoint(any(MountInstance.class),
123                         any(InstanceIdentifier.class))).thenReturn(prepareCnDataForMountPointTest());
124         MountInstance mountInstance = mock(MountInstance.class);
125         when(mountInstance.getSchemaContext()).thenReturn(schemaContextTestModule);
126         MountService mockMountService = mock(MountService.class);
127         when(mockMountService.getMountPoint(any(InstanceIdentifier.class))).thenReturn(mountInstance);
128
129         ControllerContext.getInstance().setMountService(mockMountService);
130
131         String uri = "/config/ietf-interfaces:interfaces/interface/0/yang-ext:mount/test-module:cont/cont1";
132         assertEquals(200, get(uri, MediaType.APPLICATION_XML));
133
134         uri = "/config/ietf-interfaces:interfaces/yang-ext:mount/test-module:cont/cont1";
135         assertEquals(200, get(uri, MediaType.APPLICATION_XML));
136     }
137
138     @Test
139     public void getDataMountPointIntoHighestElement() throws UnsupportedEncodingException, URISyntaxException {
140         when(
141                 brokerFacade.readConfigurationDataBehindMountPoint(any(MountInstance.class),
142                         any(InstanceIdentifier.class))).thenReturn(prepareCnDataForMountPointTest());
143         MountInstance mountInstance = mock(MountInstance.class);
144         when(mountInstance.getSchemaContext()).thenReturn(schemaContextTestModule);
145         MountService mockMountService = mock(MountService.class);
146         when(mockMountService.getMountPoint(any(InstanceIdentifier.class))).thenReturn(mountInstance);
147
148         ControllerContext.getInstance().setMountService(mockMountService);
149
150         String uri = "/config/ietf-interfaces:interfaces/interface/0/yang-ext:mount/";
151         assertEquals(200, get(uri, MediaType.APPLICATION_XML));
152     }
153
154     // /modules
155     @Test
156     public void getModulesTest() throws UnsupportedEncodingException, FileNotFoundException {
157         ControllerContext.getInstance().setGlobalSchema(schemaContextModules);
158
159         String uri = "/modules";
160
161         Response response = target(uri).request("application/yang.api+json").get();
162         validateModulesResponseJson(response);
163
164         response = target(uri).request("application/yang.api+xml").get();
165         validateModulesResponseXml(response);
166     }
167
168     // /modules/module
169     @Test
170     public void getModuleTest() throws FileNotFoundException, UnsupportedEncodingException {
171         ControllerContext.getInstance().setGlobalSchema(schemaContextModules);
172
173         String uri = "/modules/module/module2/2014-01-02";
174
175         Response response = target(uri).request("application/yang.api+xml").get();
176         assertEquals(200, response.getStatus());
177         String responseBody = response.readEntity(String.class);
178         assertTrue("Module2 in xml wasn't found", prepareXmlRegex("module2", "2014-01-02", "module:2", responseBody)
179                 .find());
180         String[] split = responseBody.split("<module");
181         assertEquals("<module element is returned more then once",2,split.length);
182
183         response = target(uri).request("application/yang.api+json").get();
184         assertEquals(200, response.getStatus());
185         responseBody = response.readEntity(String.class);
186         assertTrue("Module2 in json wasn't found", prepareJsonRegex("module2", "2014-01-02", "module:2", responseBody)
187                 .find());
188         split = responseBody.split("\"module\"");
189         assertEquals("\"module\" element is returned more then once",2,split.length);
190
191     }
192
193     // /operations
194     @Test
195     public void getOperationsTest() throws FileNotFoundException, UnsupportedEncodingException {
196         ControllerContext.getInstance().setGlobalSchema(schemaContextModules);
197
198         String uri = "/operations";
199
200         Response response = target(uri).request("application/yang.api+xml").get();
201         assertEquals(200, response.getStatus());
202         String responseBody = response.readEntity(String.class);
203         assertTrue("Xml response for /operations dummy-rpc1-module1 is incorrect",
204                 validateOperationsResponseXml(responseBody, "dummy-rpc1-module1", "module:1").find());
205         assertTrue("Xml response for /operations dummy-rpc2-module1 is incorrect",
206                 validateOperationsResponseXml(responseBody, "dummy-rpc2-module1", "module:1").find());
207         assertTrue("Xml response for /operations dummy-rpc1-module2 is incorrect",
208                 validateOperationsResponseXml(responseBody, "dummy-rpc1-module2", "module:2").find());
209         assertTrue("Xml response for /operations dummy-rpc2-module2 is incorrect",
210                 validateOperationsResponseXml(responseBody, "dummy-rpc2-module2", "module:2").find());
211
212         response = target(uri).request("application/yang.api+json").get();
213         assertEquals(200, response.getStatus());
214         responseBody = response.readEntity(String.class);
215         assertTrue("Json response for /operations dummy-rpc1-module1 is incorrect",
216                 validateOperationsResponseJson(responseBody, "dummy-rpc1-module1", "module1").find());
217         assertTrue("Json response for /operations dummy-rpc2-module1 is incorrect",
218                 validateOperationsResponseJson(responseBody, "dummy-rpc2-module1", "module1").find());
219         assertTrue("Json response for /operations dummy-rpc1-module2 is incorrect",
220                 validateOperationsResponseJson(responseBody, "dummy-rpc1-module2", "module2").find());
221         assertTrue("Json response for /operations dummy-rpc2-module2 is incorrect",
222                 validateOperationsResponseJson(responseBody, "dummy-rpc2-module2", "module2").find());
223
224     }
225
226     // /operations/pathToMountPoint/yang-ext:mount
227     @Test
228     public void getOperationsBehindMountPointTest() throws FileNotFoundException, UnsupportedEncodingException {
229         ControllerContext controllerContext = ControllerContext.getInstance();
230         controllerContext.setGlobalSchema(schemaContextModules);
231
232         MountInstance mountInstance = mock(MountInstance.class);
233         when(mountInstance.getSchemaContext()).thenReturn(schemaContextBehindMountPoint);
234         MountService mockMountService = mock(MountService.class);
235         when(mockMountService.getMountPoint(any(InstanceIdentifier.class))).thenReturn(mountInstance);
236
237         controllerContext.setMountService(mockMountService);
238
239         String uri = "/operations/ietf-interfaces:interfaces/interface/0/yang-ext:mount/";
240
241         Response response = target(uri).request("application/yang.api+xml").get();
242         assertEquals(200, response.getStatus());
243         String responseBody = response.readEntity(String.class);
244         assertTrue("Xml response for /operations/mount_point rpc-behind-module1 is incorrect",
245                 validateOperationsResponseXml(responseBody, "rpc-behind-module1", "module:1:behind:mount:point").find());
246         assertTrue("Xml response for /operations/mount_point rpc-behind-module2 is incorrect",
247                 validateOperationsResponseXml(responseBody, "rpc-behind-module2", "module:2:behind:mount:point").find());
248
249         response = target(uri).request("application/yang.api+json").get();
250         assertEquals(200, response.getStatus());
251         responseBody = response.readEntity(String.class);
252         assertTrue("Json response for /operations/mount_point rpc-behind-module1 is incorrect",
253                 validateOperationsResponseJson(responseBody, "rpc-behind-module1", "module1-behind-mount-point").find());
254         assertTrue("Json response for /operations/mount_point rpc-behind-module2 is incorrect",
255                 validateOperationsResponseJson(responseBody, "rpc-behind-module2", "module2-behind-mount-point").find());
256
257     }
258
259     private Matcher validateOperationsResponseJson(String searchIn, String rpcName, String moduleName) {
260         StringBuilder regex = new StringBuilder();
261         regex.append("^");
262
263         regex.append(".*\\{");
264         regex.append(".*\"");
265
266         // operations prefix optional
267         regex.append("(");
268         regex.append("ietf-restconf:");
269         regex.append("|)");
270         // :operations prefix optional
271
272         regex.append("operations\"");
273         regex.append(".*:");
274         regex.append(".*\\{");
275
276         regex.append(".*\"" + moduleName);
277         regex.append(":");
278         regex.append(rpcName + "\"");
279         regex.append(".*\\[");
280         regex.append(".*null");
281         regex.append(".*\\]");
282
283         regex.append(".*\\}");
284         regex.append(".*\\}");
285
286         regex.append(".*");
287         regex.append("$");
288         Pattern ptrn = Pattern.compile(regex.toString(), Pattern.DOTALL);
289         return ptrn.matcher(searchIn);
290
291     }
292
293     private Matcher validateOperationsResponseXml(String searchIn, String rpcName, String namespace) {
294         StringBuilder regex = new StringBuilder();
295
296         regex.append("^");
297
298         regex.append(".*<operations");
299         regex.append(".*xmlns=\"urn:ietf:params:xml:ns:yang:ietf-restconf\"");
300         regex.append(".*>");
301
302         regex.append(".*<");
303         regex.append(".*" + rpcName);
304         regex.append(".*" + namespace);
305         regex.append(".*/");
306         regex.append(".*>");
307
308         regex.append(".*</operations.*");
309         regex.append(".*>");
310
311         regex.append(".*");
312         regex.append("$");
313         Pattern ptrn = Pattern.compile(regex.toString(), Pattern.DOTALL);
314         return ptrn.matcher(searchIn);
315     }
316
317     // /restconf/modules/pathToMountPoint/yang-ext:mount
318     @Test
319     public void getModulesBehindMountPoint() throws FileNotFoundException, UnsupportedEncodingException {
320         ControllerContext controllerContext = ControllerContext.getInstance();
321         controllerContext.setGlobalSchema(schemaContextModules);
322
323         MountInstance mountInstance = mock(MountInstance.class);
324         when(mountInstance.getSchemaContext()).thenReturn(schemaContextBehindMountPoint);
325         MountService mockMountService = mock(MountService.class);
326         when(mockMountService.getMountPoint(any(InstanceIdentifier.class))).thenReturn(mountInstance);
327
328         controllerContext.setMountService(mockMountService);
329
330         String uri = "/modules/ietf-interfaces:interfaces/interface/0/yang-ext:mount/";
331
332         Response response = target(uri).request("application/yang.api+json").get();
333         assertEquals(200, response.getStatus());
334         String responseBody = response.readEntity(String.class);
335
336         assertTrue(
337                 "module1-behind-mount-point in json wasn't found",
338                 prepareJsonRegex("module1-behind-mount-point", "2014-02-03", "module:1:behind:mount:point",
339                         responseBody).find());
340         assertTrue(
341                 "module2-behind-mount-point in json wasn't found",
342                 prepareJsonRegex("module2-behind-mount-point", "2014-02-04", "module:2:behind:mount:point",
343                         responseBody).find());
344
345         response = target(uri).request("application/yang.api+xml").get();
346         assertEquals(200, response.getStatus());
347         responseBody = response.readEntity(String.class);
348         assertTrue(
349                 "module1-behind-mount-point in json wasn't found",
350                 prepareXmlRegex("module1-behind-mount-point", "2014-02-03", "module:1:behind:mount:point", responseBody)
351                         .find());
352         assertTrue(
353                 "module2-behind-mount-point in json wasn't found",
354                 prepareXmlRegex("module2-behind-mount-point", "2014-02-04", "module:2:behind:mount:point", responseBody)
355                         .find());
356
357     }
358
359     // /restconf/modules/module/pathToMountPoint/yang-ext:mount/moduleName/revision
360     @Test
361     public void getModuleBehindMountPoint() throws FileNotFoundException, UnsupportedEncodingException {
362         ControllerContext controllerContext = ControllerContext.getInstance();
363         controllerContext.setGlobalSchema(schemaContextModules);
364
365         MountInstance mountInstance = mock(MountInstance.class);
366         when(mountInstance.getSchemaContext()).thenReturn(schemaContextBehindMountPoint);
367         MountService mockMountService = mock(MountService.class);
368         when(mockMountService.getMountPoint(any(InstanceIdentifier.class))).thenReturn(mountInstance);
369
370         controllerContext.setMountService(mockMountService);
371
372         String uri = "/modules/module/ietf-interfaces:interfaces/interface/0/yang-ext:mount/module1-behind-mount-point/2014-02-03";
373
374         Response response = target(uri).request("application/yang.api+json").get();
375         assertEquals(200, response.getStatus());
376         String responseBody = response.readEntity(String.class);
377
378         assertTrue(
379                 "module1-behind-mount-point in json wasn't found",
380                 prepareJsonRegex("module1-behind-mount-point", "2014-02-03", "module:1:behind:mount:point",
381                         responseBody).find());
382         String[] split = responseBody.split("\"module\"");
383         assertEquals("\"module\" element is returned more then once",2,split.length);
384
385
386         response = target(uri).request("application/yang.api+xml").get();
387         assertEquals(200, response.getStatus());
388         responseBody = response.readEntity(String.class);
389         assertTrue(
390                 "module1-behind-mount-point in json wasn't found",
391                 prepareXmlRegex("module1-behind-mount-point", "2014-02-03", "module:1:behind:mount:point", responseBody)
392                         .find());
393         split = responseBody.split("<module");
394         assertEquals("<module element is returned more then once",2,split.length);
395
396
397
398
399     }
400
401     private void validateModulesResponseXml(Response response) {
402         assertEquals(200, response.getStatus());
403         String responseBody = response.readEntity(String.class);
404
405         assertTrue("Module1 in xml wasn't found", prepareXmlRegex("module1", "2014-01-01", "module:1", responseBody)
406                 .find());
407         assertTrue("Module2 in xml wasn't found", prepareXmlRegex("module2", "2014-01-02", "module:2", responseBody)
408                 .find());
409         assertTrue("Module3 in xml wasn't found", prepareXmlRegex("module3", "2014-01-03", "module:3", responseBody)
410                 .find());
411     }
412
413     private void validateModulesResponseJson(Response response) {
414         assertEquals(200, response.getStatus());
415         String responseBody = response.readEntity(String.class);
416
417         assertTrue("Module1 in json wasn't found", prepareJsonRegex("module1", "2014-01-01", "module:1", responseBody)
418                 .find());
419         assertTrue("Module2 in json wasn't found", prepareJsonRegex("module2", "2014-01-02", "module:2", responseBody)
420                 .find());
421         assertTrue("Module3 in json wasn't found", prepareJsonRegex("module3", "2014-01-03", "module:3", responseBody)
422                 .find());
423     }
424
425     private Matcher prepareJsonRegex(String module, String revision, String namespace, String searchIn) {
426         StringBuilder regex = new StringBuilder();
427         regex.append("^");
428
429         regex.append(".*\\{");
430         regex.append(".*\"name\"");
431         regex.append(".*:");
432         regex.append(".*\"" + module + "\",");
433
434         regex.append(".*\"revision\"");
435         regex.append(".*:");
436         regex.append(".*\"" + revision + "\",");
437
438         regex.append(".*\"namespace\"");
439         regex.append(".*:");
440         regex.append(".*\"" + namespace + "\"");
441
442         regex.append(".*\\}");
443
444         regex.append(".*");
445         regex.append("$");
446         Pattern ptrn = Pattern.compile(regex.toString(), Pattern.DOTALL);
447         return ptrn.matcher(searchIn);
448
449     }
450
451     private Matcher prepareXmlRegex(String module, String revision, String namespace, String searchIn) {
452         StringBuilder regex = new StringBuilder();
453         regex.append("^");
454
455         regex.append(".*<module.*");
456         regex.append(".*>");
457
458         regex.append(".*<name>");
459         regex.append(".*" + module);
460         regex.append(".*<\\/name>");
461
462         regex.append(".*<revision>");
463         regex.append(".*" + revision);
464         regex.append(".*<\\/revision>");
465
466         regex.append(".*<namespace>");
467         regex.append(".*" + namespace);
468         regex.append(".*<\\/namespace>");
469
470         regex.append(".*<\\/module.*>");
471
472         regex.append(".*");
473         regex.append("$");
474
475         Pattern ptrn = Pattern.compile(regex.toString(), Pattern.DOTALL);
476         return ptrn.matcher(searchIn);
477     }
478
479     private void prepareMockForModulesTest(ControllerContext mockedControllerContext) throws FileNotFoundException {
480         SchemaContext schemaContext = TestUtils.loadSchemaContext("/modules");
481         mockedControllerContext.setGlobalSchema(schemaContext);
482         // when(mockedControllerContext.getGlobalSchema()).thenReturn(schemaContext);
483     }
484
485     private int get(String uri, String mediaType) {
486         return target(uri).request(mediaType).get().getStatus();
487     }
488
489     private CompositeNode prepareCnDataForMountPointTest() throws URISyntaxException {
490         CompositeNodeWrapper cont1 = new CompositeNodeWrapper(new URI("test:module"), "cont1");
491         SimpleNodeWrapper lf11 = new SimpleNodeWrapper(new URI("test:module"), "lf11", "lf11 value");
492         cont1.addValue(lf11);
493         return cont1.unwrap();
494     }
495
496     private void mockReadOperationalDataMethod() {
497         when(brokerFacade.readOperationalData(any(InstanceIdentifier.class))).thenReturn(answerFromGet);
498     }
499
500     private void mockReadConfigurationDataMethod() {
501         when(brokerFacade.readConfigurationData(any(InstanceIdentifier.class))).thenReturn(answerFromGet);
502     }
503
504     private static CompositeNode prepareCompositeNodeWithIetfInterfacesInterfacesData() {
505         CompositeNode intface;
506         try {
507             intface = new CompositeNodeWrapper(new URI("interface"), "interface");
508             List<Node<?>> childs = new ArrayList<>();
509
510             childs.add(new SimpleNodeWrapper(new URI("name"), "name", "eth0"));
511             childs.add(new SimpleNodeWrapper(new URI("type"), "type", "ethernetCsmacd"));
512             childs.add(new SimpleNodeWrapper(new URI("enabled"), "enabled", Boolean.FALSE));
513             childs.add(new SimpleNodeWrapper(new URI("description"), "description", "some interface"));
514             intface.setValue(childs);
515             return intface;
516         } catch (URISyntaxException e) {
517         }
518
519         return null;
520     }
521
522 }