Bug 1010: Implement restconf error responses
[controller.git] / opendaylight / md-sal / sal-rest-connector / src / test / java / org / opendaylight / controller / sal / restconf / impl / json / to / cnsn / test / JsonToCnSnTest.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.json.to.cnsn.test;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertNotNull;
12 import static org.junit.Assert.assertTrue;
13
14 import java.util.HashSet;
15 import java.util.List;
16 import java.util.Set;
17
18 import org.junit.Ignore;
19 import org.junit.Test;
20 import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider;
21 import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
22 import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
23 import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
24 import org.opendaylight.yangtools.yang.common.QName;
25 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
26 import org.opendaylight.yangtools.yang.data.api.Node;
27 import org.opendaylight.yangtools.yang.data.api.SimpleNode;
28 import org.opendaylight.yangtools.yang.model.api.Module;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 public class JsonToCnSnTest {
33
34     private static final Logger LOG = LoggerFactory.getLogger(JsonToCnSnTest.class);
35
36     @Test
37     public void simpleListTest() {
38         simpleTest("/json-to-cnsn/simple-list.json", "/json-to-cnsn/simple-list-yang/1", "lst", "simple:list:yang1",
39                 "simple-list-yang1");
40     }
41
42     @Test
43     public void simpleContainerTest() {
44         simpleTest("/json-to-cnsn/simple-container.json", "/json-to-cnsn/simple-container-yang", "cont",
45                 "simple:container:yang", "simple-container-yang");
46     }
47
48     /**
49      * test if for every leaf list item is simple node instance created
50      */
51     @Test
52     public void multipleItemsInLeafList() {
53         CompositeNode compositeNode = TestUtils.readInputToCnSn("/json-to-cnsn/multiple-leaflist-items.json", true,
54                 JsonToCompositeNodeProvider.INSTANCE);
55         assertNotNull(compositeNode);
56         assertEquals(3, compositeNode.getValue().size());
57
58         boolean lflst1_1 = false;
59         boolean lflst1_2 = false;
60         boolean lflst1_3 = false;
61
62         for (Node<?> node : compositeNode.getValue()) {
63             assertEquals("lflst1", node.getNodeType().getLocalName());
64             assertTrue(node instanceof SimpleNode<?>);
65             SimpleNode<?> simpleNode = (SimpleNode<?>) node;
66             if (simpleNode.getValue().equals("45")) {
67                 lflst1_1 = true;
68             } else if (simpleNode.getValue().equals("55")) {
69                 lflst1_2 = true;
70             } else if (simpleNode.getValue().equals("66")) {
71                 lflst1_3 = true;
72             }
73         }
74
75         assertTrue(lflst1_1);
76         assertTrue(lflst1_2);
77         assertTrue(lflst1_3);
78
79     }
80
81     /**
82      * List contains 4 items and in every item are other elements. It is
83      * supposed that there should be: lf11, lflst11, cont11, lst11
84      */
85     @Test
86     public void multipleItemsInListTest() {
87         CompositeNode compositeNode = TestUtils.readInputToCnSn("/json-to-cnsn/multiple-items-in-list.json", true,
88                 JsonToCompositeNodeProvider.INSTANCE);
89
90         assertNotNull(compositeNode);
91         assertEquals("lst", compositeNode.getNodeType().getLocalName());
92
93         verityMultipleItemsInList(compositeNode);
94     }
95
96     @Test
97     public void nullArrayToSimpleNodeWithNullValueTest() {
98         CompositeNode compositeNode = TestUtils.readInputToCnSn("/json-to-cnsn/array-with-null.json", true,
99                 JsonToCompositeNodeProvider.INSTANCE);
100         assertNotNull(compositeNode);
101         assertEquals("cont", compositeNode.getNodeType().getLocalName());
102
103         assertNotNull(compositeNode.getValue());
104         assertEquals(1, compositeNode.getValue().size());
105         Node<?> lfNode = compositeNode.getValue().iterator().next();
106
107         assertTrue(lfNode instanceof SimpleNode<?>);
108         assertEquals(null, ((SimpleNode<?>) lfNode).getValue());
109
110     }
111
112     @Test
113     public void incorrectTopLevelElementsTest() {
114         RestconfDocumentedException cause1 = null;
115         try {
116             TestUtils.readInputToCnSn("/json-to-cnsn/wrong-top-level1.json", true, JsonToCompositeNodeProvider.INSTANCE);
117         } catch (RestconfDocumentedException e) {
118             cause1 = e;
119         }
120
121         assertNotNull(cause1);
122         assertTrue(cause1.getErrors().get( 0 ).getErrorMessage().contains(
123             "First element in Json Object has to be \"Object\" or \"Array with one Object element\". Other scenarios are not supported yet."));
124
125         RestconfDocumentedException cause2 = null;
126         try {
127             TestUtils
128                     .readInputToCnSn("/json-to-cnsn/wrong-top-level2.json", true, JsonToCompositeNodeProvider.INSTANCE);
129         } catch (RestconfDocumentedException e) {
130             cause2 = e;
131         }
132         assertNotNull(cause2);
133         assertTrue(cause2.getErrors().get( 0 ).getErrorMessage().contains(
134                                                      "Json Object should contain one element"));
135
136         RestconfDocumentedException cause3 = null;
137         try {
138             TestUtils
139
140                     .readInputToCnSn("/json-to-cnsn/wrong-top-level3.json", true, JsonToCompositeNodeProvider.INSTANCE);
141         } catch (RestconfDocumentedException e) {
142             cause3 = e;
143         }
144         assertNotNull(cause3);
145         assertTrue(cause3.getErrors().get( 0 ).getErrorMessage().contains(
146             "First element in Json Object has to be \"Object\" or \"Array with one Object element\". Other scenarios are not supported yet."));
147
148     }
149
150     /**
151      * if leaf list with no data is in json then no corresponding data is
152      * created in composite node. if leaf with no data then exception is raised
153      */
154     @Test
155     public void emptyDataReadTest() {
156         CompositeNode compositeNode = TestUtils.readInputToCnSn("/json-to-cnsn/empty-data.json", true,
157                 JsonToCompositeNodeProvider.INSTANCE);
158
159         assertNotNull(compositeNode);
160
161         assertEquals("cont", compositeNode.getNodeType().getLocalName());
162         assertTrue(compositeNode instanceof CompositeNode);
163         List<Node<?>> children = compositeNode.getValue();
164         assertEquals(1, children.size());
165         assertEquals("lflst2", children.get(0).getNodeType().getLocalName());
166         assertEquals("45", children.get(0).getValue());
167
168         String reason = null;
169         try {
170             TestUtils.readInputToCnSn("/json-to-cnsn/empty-data1.json", true, JsonToCompositeNodeProvider.INSTANCE);
171         } catch (RestconfDocumentedException e) {
172             reason = e.getErrors().get( 0 ).getErrorMessage();
173         }
174
175         assertTrue(reason.contains("Expected value at line"));
176
177     }
178
179     /**
180      * Tests whether namespace <b>stay unchanged</b> if concrete values are
181      * present in composite or simple node and if the method for update is
182      * called.
183      *
184      */
185     @Test
186     public void notSupplyNamespaceIfAlreadySupplied() {
187
188         CompositeNode compositeNode = TestUtils.readInputToCnSn("/json-to-cnsn/simple-list.json", false,
189                 JsonToCompositeNodeProvider.INSTANCE);
190         assertNotNull(compositeNode);
191
192         // supplement namespaces according to first data schema -
193         // "simple:data:types1"
194         Set<Module> modules1 = new HashSet<>();
195         Set<Module> modules2 = new HashSet<>();
196         modules1 = TestUtils.loadModulesFrom("/json-to-cnsn/simple-list-yang/1");
197         modules2 = TestUtils.loadModulesFrom("/json-to-cnsn/simple-list-yang/2");
198         assertNotNull(modules1);
199         assertNotNull(modules2);
200
201         TestUtils.normalizeCompositeNode(compositeNode, modules1, "simple-list-yang1:lst");
202
203         assertTrue(compositeNode instanceof CompositeNodeWrapper);
204         CompositeNode compNode = ((CompositeNodeWrapper) compositeNode).unwrap();
205
206         assertEquals("lst", compNode.getNodeType().getLocalName());
207         verifyCompositeNode(compNode, "simple:list:yang1");
208
209         TestUtils.normalizeCompositeNode(compositeNode, modules2, "simple-list-yang2:lst");
210         verifyCompositeNode(compNode, "simple:list:yang1");
211     }
212
213     @Test
214     public void jsonIdentityrefToCompositeNode() {
215         CompositeNode compositeNode = TestUtils.readInputToCnSn("/json-to-cnsn/identityref/json/data.json", false,
216                 JsonToCompositeNodeProvider.INSTANCE);
217         assertNotNull(compositeNode);
218
219         Set<Module> modules = TestUtils.loadModulesFrom("/json-to-cnsn/identityref");
220         assertEquals(2, modules.size());
221
222         TestUtils.normalizeCompositeNode(compositeNode, modules, "identityref-module:cont");
223
224         assertEquals("cont", compositeNode.getNodeType().getLocalName());
225
226         List<Node<?>> childs = compositeNode.getValue();
227         assertEquals(1, childs.size());
228         Node<?> nd = childs.iterator().next();
229         assertTrue(nd instanceof CompositeNode);
230         assertEquals("cont1", nd.getNodeType().getLocalName());
231
232         childs = ((CompositeNode) nd).getValue();
233         assertEquals(4, childs.size());
234         SimpleNode<?> lf11 = null;
235         SimpleNode<?> lf12 = null;
236         SimpleNode<?> lf13 = null;
237         SimpleNode<?> lf14 = null;
238         for (Node<?> child : childs) {
239             assertTrue(child instanceof SimpleNode);
240             if (child.getNodeType().getLocalName().equals("lf11")) {
241                 lf11 = (SimpleNode<?>) child;
242             } else if (child.getNodeType().getLocalName().equals("lf12")) {
243                 lf12 = (SimpleNode<?>) child;
244             } else if (child.getNodeType().getLocalName().equals("lf13")) {
245                 lf13 = (SimpleNode<?>) child;
246             } else if (child.getNodeType().getLocalName().equals("lf14")) {
247                 lf14 = (SimpleNode<?>) child;
248             }
249         }
250
251         assertTrue(lf11.getValue() instanceof QName);
252         assertEquals("iden", ((QName) lf11.getValue()).getLocalName());
253         assertEquals("identity:module", ((QName) lf11.getValue()).getNamespace().toString());
254
255         assertTrue(lf12.getValue() instanceof QName);
256         assertEquals("iden_local", ((QName) lf12.getValue()).getLocalName());
257         assertEquals("identityref:module", ((QName) lf12.getValue()).getNamespace().toString());
258
259         assertTrue(lf13.getValue() instanceof QName);
260         assertEquals("iden_local", ((QName) lf13.getValue()).getLocalName());
261         assertEquals("identityref:module", ((QName) lf13.getValue()).getNamespace().toString());
262
263         assertTrue(lf14.getValue() instanceof QName);
264         assertEquals("iden_local", ((QName) lf14.getValue()).getLocalName());
265         assertEquals("identity:module", ((QName) lf14.getValue()).getNamespace().toString());
266     }
267
268     @Ignore
269     @Test
270     public void loadDataAugmentedSchemaMoreEqualNamesTest() {
271         loadAndNormalizeData("/common/augment/json/dataa.json", "/common/augment/yang", "cont", "main");
272         loadAndNormalizeData("/common/augment/json/datab.json", "/common/augment/yang", "cont", "main");
273
274     }
275
276     private void simpleTest(final String jsonPath, final String yangPath, final String topLevelElementName, final String namespace,
277             final String moduleName) {
278         CompositeNode compNode = loadAndNormalizeData(jsonPath, yangPath, topLevelElementName, moduleName);
279         verifyCompositeNode(compNode, namespace);
280     }
281
282     private CompositeNode loadAndNormalizeData(final String jsonPath, final String yangPath, final String topLevelElementName, final String moduleName) {
283         CompositeNode compositeNode = TestUtils.readInputToCnSn(jsonPath, false, JsonToCompositeNodeProvider.INSTANCE);
284         assertNotNull(compositeNode);
285
286         Set<Module> modules = null;
287         modules = TestUtils.loadModulesFrom(yangPath);
288         assertNotNull(modules);
289
290         TestUtils.normalizeCompositeNode(compositeNode, modules, moduleName + ":" + topLevelElementName);
291
292         assertTrue(compositeNode instanceof CompositeNodeWrapper);
293         CompositeNode compNode = ((CompositeNodeWrapper) compositeNode).unwrap();
294
295         assertEquals(topLevelElementName, compNode.getNodeType().getLocalName());
296         return compNode;
297     }
298
299     private void verityMultipleItemsInList(final CompositeNode compositeNode) {
300         List<Node<?>> childrenNodes = compositeNode.getValue();
301         assertEquals(4, childrenNodes.size());
302         boolean lf11Found = false;
303         boolean cont11Found = false;
304         boolean lst11Found = false;
305         for (Node<?> lst1Item : childrenNodes) {
306             assertEquals("lst1", lst1Item.getNodeType().getLocalName());
307             assertTrue(lst1Item instanceof CompositeNode);
308
309             List<Node<?>> childrenLst1 = ((CompositeNode) lst1Item).getValue();
310             assertEquals(1, childrenLst1.size());
311             String localName = childrenLst1.get(0).getNodeType().getLocalName();
312             if (localName.equals("lf11")) {
313                 assertTrue(childrenLst1.get(0) instanceof SimpleNode);
314                 lf11Found = true;
315             } else if (localName.equals("lflst11")) {
316                 assertTrue(childrenLst1.get(0) instanceof SimpleNode);
317                 assertEquals("45", ((SimpleNode<?>) childrenLst1.get(0)).getValue());
318                 lf11Found = true;
319             } else if (localName.equals("cont11")) {
320                 assertTrue(childrenLst1.get(0) instanceof CompositeNode);
321                 cont11Found = true;
322             } else if (localName.equals("lst11")) {
323                 lst11Found = true;
324                 assertTrue(childrenLst1.get(0) instanceof CompositeNode);
325                 assertEquals(0, ((CompositeNode) childrenLst1.get(0)).getValue().size());
326             }
327
328         }
329         assertTrue(lf11Found);
330         assertTrue(cont11Found);
331         assertTrue(lst11Found);
332     }
333
334     private void verifyCompositeNode(final CompositeNode compositeNode, final String namespace) {
335         boolean cont1Found = false;
336         boolean lst1Found = false;
337         boolean lflst1_1Found = false;
338         boolean lflst1_2Found = false;
339         boolean lf1Found = false;
340
341         // assertEquals(namespace,
342         // compositeNode.getNodeType().getNamespace().toString());
343
344         for (Node<?> node : compositeNode.getValue()) {
345             if (node.getNodeType().getLocalName().equals("cont1")) {
346                 if (node instanceof CompositeNode) {
347                     cont1Found = true;
348                     assertEquals(0, ((CompositeNode) node).getValue().size());
349                 }
350             } else if (node.getNodeType().getLocalName().equals("lst1")) {
351                 if (node instanceof CompositeNode) {
352                     lst1Found = true;
353                     assertEquals(0, ((CompositeNode) node).getValue().size());
354                 }
355             } else if (node.getNodeType().getLocalName().equals("lflst1")) {
356                 if (node instanceof SimpleNode) {
357                     if (((SimpleNode<?>) node).getValue().equals("lflst1_1")) {
358                         lflst1_1Found = true;
359                     } else if (((SimpleNode<?>) node).getValue().equals("lflst1_2")) {
360                         lflst1_2Found = true;
361                     }
362                 }
363
364             } else if (node.getNodeType().getLocalName().equals("lf1")) {
365                 if (node instanceof SimpleNode) {
366                     if (((SimpleNode<?>) node).getValue().equals("lf1")) {
367                         lf1Found = true;
368                     }
369                 }
370             }
371             assertEquals(namespace, node.getNodeType().getNamespace().toString());
372         }
373         assertTrue(cont1Found);
374         assertTrue(lst1Found);
375         assertTrue(lflst1_1Found);
376         assertTrue(lflst1_2Found);
377         assertTrue(lf1Found);
378     }
379
380     @Test
381     public void unsupportedDataFormatTest() {
382         String exceptionMessage = "";
383         try {
384             TestUtils.readInputToCnSn("/json-to-cnsn/unsupported-json-format.json", true,
385                     JsonToCompositeNodeProvider.INSTANCE);
386         } catch (RestconfDocumentedException e) {
387             exceptionMessage = e.getErrors().get( 0 ).getErrorMessage();
388         }
389         assertTrue(exceptionMessage.contains("Root element of Json has to be Object"));
390     }
391
392 }