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