2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.restconf.nb.rfc8040.rests.utils;
11 import static org.junit.Assert.assertEquals;
12 import static org.junit.Assert.assertNotNull;
13 import static org.junit.Assert.assertNull;
14 import static org.junit.Assert.fail;
15 import static org.mockito.Mockito.doReturn;
16 import static org.mockito.Mockito.when;
18 import com.google.common.base.Optional;
19 import com.google.common.util.concurrent.Futures;
20 import java.util.Collections;
21 import javax.ws.rs.core.MultivaluedHashMap;
22 import javax.ws.rs.core.UriInfo;
23 import org.junit.Before;
24 import org.junit.Test;
25 import org.mockito.Mock;
26 import org.mockito.Mockito;
27 import org.mockito.MockitoAnnotations;
28 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
29 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
30 import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
31 import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
32 import org.opendaylight.restconf.common.context.WriterParameters;
33 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
34 import org.opendaylight.restconf.common.errors.RestconfError.ErrorTag;
35 import org.opendaylight.restconf.common.errors.RestconfError.ErrorType;
36 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.TransactionVarsWrapper;
37 import org.opendaylight.yangtools.yang.common.QName;
38 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
39 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
40 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
41 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
42 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
43 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
44 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
45 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
47 public class ReadDataTransactionUtilTest {
49 private static final TestData DATA = new TestData();
50 private static final YangInstanceIdentifier.NodeIdentifier NODE_IDENTIFIER = new YangInstanceIdentifier
51 .NodeIdentifier(QName.create("ns", "2016-02-28", "container"));
53 private TransactionVarsWrapper wrapper;
55 private DOMTransactionChain transactionChain;
57 private InstanceIdentifierContext<ContainerSchemaNode> context;
59 private DOMDataReadOnlyTransaction read;
61 private SchemaContext schemaContext;
63 private ContainerSchemaNode containerSchemaNode;
65 private LeafSchemaNode containerChildNode;
66 private QName containerChildQName;
70 MockitoAnnotations.initMocks(this);
72 containerChildQName = QName.create("ns", "2016-02-28", "container-child");
74 when(transactionChain.newReadOnlyTransaction()).thenReturn(read);
75 when(context.getSchemaContext()).thenReturn(schemaContext);
76 when(context.getSchemaNode()).thenReturn(containerSchemaNode);
77 when(containerSchemaNode.getQName()).thenReturn(NODE_IDENTIFIER.getNodeType());
78 when(containerChildNode.getQName()).thenReturn(containerChildQName);
79 when(containerSchemaNode.getDataChildByName(containerChildQName)).thenReturn(containerChildNode);
81 wrapper = new TransactionVarsWrapper(this.context, null, this.transactionChain);
85 public void readDataConfigTest() {
86 doReturn(Futures.immediateCheckedFuture(Optional.of(DATA.data3))).when(read)
87 .read(LogicalDatastoreType.CONFIGURATION, DATA.path);
88 doReturn(DATA.path).when(context).getInstanceIdentifier();
89 final String valueOfContent = RestconfDataServiceConstant.ReadData.CONFIG;
90 final NormalizedNode<?, ?> normalizedNode =
91 ReadDataTransactionUtil.readData(valueOfContent, wrapper, schemaContext);
92 assertEquals(DATA.data3, normalizedNode);
96 public void readAllHavingOnlyConfigTest() {
97 doReturn(Futures.immediateCheckedFuture(Optional.of(DATA.data3))).when(read)
98 .read(LogicalDatastoreType.CONFIGURATION, DATA.path);
99 doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(read)
100 .read(LogicalDatastoreType.OPERATIONAL, DATA.path);
101 doReturn(DATA.path).when(context).getInstanceIdentifier();
102 final String valueOfContent = RestconfDataServiceConstant.ReadData.ALL;
103 final NormalizedNode<?, ?> normalizedNode =
104 ReadDataTransactionUtil.readData(valueOfContent, wrapper, schemaContext);
105 assertEquals(DATA.data3, normalizedNode);
109 public void readAllHavingOnlyNonConfigTest() {
110 doReturn(Futures.immediateCheckedFuture(Optional.of(DATA.data2))).when(read)
111 .read(LogicalDatastoreType.OPERATIONAL, DATA.path2);
112 doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(read)
113 .read(LogicalDatastoreType.CONFIGURATION, DATA.path2);
114 doReturn(DATA.path2).when(context).getInstanceIdentifier();
115 final String valueOfContent = RestconfDataServiceConstant.ReadData.ALL;
116 final NormalizedNode<?, ?> normalizedNode =
117 ReadDataTransactionUtil.readData(valueOfContent, wrapper, schemaContext);
118 assertEquals(DATA.data2, normalizedNode);
122 public void readDataNonConfigTest() {
123 doReturn(Futures.immediateCheckedFuture(Optional.of(DATA.data2))).when(read)
124 .read(LogicalDatastoreType.OPERATIONAL, DATA.path2);
125 doReturn(DATA.path2).when(context).getInstanceIdentifier();
126 final String valueOfContent = RestconfDataServiceConstant.ReadData.NONCONFIG;
127 final NormalizedNode<?, ?> normalizedNode =
128 ReadDataTransactionUtil.readData(valueOfContent, wrapper, schemaContext);
129 assertEquals(DATA.data2, normalizedNode);
133 public void readContainerDataAllTest() {
134 doReturn(Futures.immediateCheckedFuture(Optional.of(DATA.data3))).when(read)
135 .read(LogicalDatastoreType.CONFIGURATION, DATA.path);
136 doReturn(Futures.immediateCheckedFuture(Optional.of(DATA.data4))).when(read)
137 .read(LogicalDatastoreType.OPERATIONAL, DATA.path);
138 doReturn(DATA.path).when(context).getInstanceIdentifier();
139 final String valueOfContent = RestconfDataServiceConstant.ReadData.ALL;
140 final NormalizedNode<?, ?> normalizedNode =
141 ReadDataTransactionUtil.readData(valueOfContent, wrapper, schemaContext);
142 final ContainerNode checkingData = Builders
144 .withNodeIdentifier(NODE_IDENTIFIER)
145 .withChild(DATA.contentLeaf)
146 .withChild(DATA.contentLeaf2)
148 assertEquals(checkingData, normalizedNode);
152 public void readContainerDataConfigNoValueOfContentTest() {
153 doReturn(Futures.immediateCheckedFuture(Optional.of(DATA.data3))).when(read)
154 .read(LogicalDatastoreType.CONFIGURATION, DATA.path);
155 doReturn(Futures.immediateCheckedFuture(Optional.of(DATA.data4))).when(read)
156 .read(LogicalDatastoreType.OPERATIONAL, DATA.path);
157 doReturn(DATA.path).when(context).getInstanceIdentifier();
158 final NormalizedNode<?, ?> normalizedNode = ReadDataTransactionUtil.readData(
159 RestconfDataServiceConstant.ReadData.ALL, wrapper, schemaContext);
160 final ContainerNode checkingData = Builders
162 .withNodeIdentifier(NODE_IDENTIFIER)
163 .withChild(DATA.contentLeaf)
164 .withChild(DATA.contentLeaf2)
166 assertEquals(checkingData, normalizedNode);
170 public void readListDataAllTest() {
171 doReturn(Futures.immediateCheckedFuture(Optional.of(DATA.listData))).when(read)
172 .read(LogicalDatastoreType.OPERATIONAL, DATA.path3);
173 doReturn(Futures.immediateCheckedFuture(Optional.of(DATA.listData2))).when(read)
174 .read(LogicalDatastoreType.CONFIGURATION, DATA.path3);
175 doReturn(DATA.path3).when(context).getInstanceIdentifier();
176 final String valueOfContent = RestconfDataServiceConstant.ReadData.ALL;
177 final NormalizedNode<?, ?> normalizedNode =
178 ReadDataTransactionUtil.readData(valueOfContent, wrapper, schemaContext);
179 final MapNode checkingData = Builders
181 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(QName.create("ns", "2016-02-28", "list")))
182 .withChild(DATA.checkData)
184 assertEquals(checkingData, normalizedNode);
188 public void readDataWrongPathOrNoContentTest() {
189 doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(read)
190 .read(LogicalDatastoreType.CONFIGURATION, DATA.path2);
191 doReturn(DATA.path2).when(context).getInstanceIdentifier();
192 final String valueOfContent = RestconfDataServiceConstant.ReadData.CONFIG;
193 final NormalizedNode<?, ?> normalizedNode =
194 ReadDataTransactionUtil.readData(valueOfContent, wrapper, schemaContext);
195 assertNull(normalizedNode);
198 @Test(expected = RestconfDocumentedException.class)
199 public void readDataFailTest() {
200 final String valueOfContent = RestconfDataServiceConstant.ReadData.READ_TYPE_TX;
201 final NormalizedNode<?, ?> normalizedNode = ReadDataTransactionUtil.readData(
202 valueOfContent, wrapper, schemaContext);
203 assertNull(normalizedNode);
207 * Test of parsing default parameters from URI request.
210 public void parseUriParametersDefaultTest() {
211 final UriInfo uriInfo = Mockito.mock(UriInfo.class);
212 final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
214 // no parameters, default values should be used
215 when(uriInfo.getQueryParameters()).thenReturn(parameters);
217 final WriterParameters parsedParameters = ReadDataTransactionUtil.parseUriParameters(context, uriInfo);
219 assertEquals("Not correctly parsed URI parameter",
220 RestconfDataServiceConstant.ReadData.ALL, parsedParameters.getContent());
221 assertNull("Not correctly parsed URI parameter",
222 parsedParameters.getDepth());
223 assertNull("Not correctly parsed URI parameter",
224 parsedParameters.getFields());
228 * Test of parsing user defined parameters from URI request.
231 public void parseUriParametersUserDefinedTest() {
232 final UriInfo uriInfo = Mockito.mock(UriInfo.class);
233 final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
235 final String content = "config";
236 final String depth = "10";
237 final String fields = containerChildQName.getLocalName();
239 parameters.put("content", Collections.singletonList(content));
240 parameters.put("depth", Collections.singletonList(depth));
241 parameters.put("fields", Collections.singletonList(fields));
243 when(uriInfo.getQueryParameters()).thenReturn(parameters);
245 final WriterParameters parsedParameters = ReadDataTransactionUtil.parseUriParameters(context, uriInfo);
248 assertEquals("Not correctly parsed URI parameter",
249 content, parsedParameters.getContent());
252 assertNotNull("Not correctly parsed URI parameter",
253 parsedParameters.getDepth());
254 assertEquals("Not correctly parsed URI parameter",
255 depth, parsedParameters.getDepth().toString());
258 assertNotNull("Not correctly parsed URI parameter",
259 parsedParameters.getFields());
260 assertEquals("Not correctly parsed URI parameter",
261 1, parsedParameters.getFields().size());
262 assertEquals("Not correctly parsed URI parameter",
263 1, parsedParameters.getFields().get(0).size());
264 assertEquals("Not correctly parsed URI parameter",
265 containerChildQName, parsedParameters.getFields().get(0).iterator().next());
269 * Negative test of parsing request URI parameters when content parameter has not allowed value.
272 public void parseUriParametersContentParameterNegativeTest() {
273 final UriInfo uriInfo = Mockito.mock(UriInfo.class);
274 final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
276 parameters.put("content", Collections.singletonList("not-allowed-parameter-value"));
277 when(uriInfo.getQueryParameters()).thenReturn(parameters);
280 ReadDataTransactionUtil.parseUriParameters(context, uriInfo);
281 fail("Test expected to fail due to not allowed parameter value");
282 } catch (final RestconfDocumentedException e) {
284 assertEquals("Error type is not correct", ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
285 assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
286 assertEquals("Error status code is not correct", 400, e.getErrors().get(0).getErrorTag().getStatusCode());
291 * Negative test of parsing request URI parameters when depth parameter has not allowed value.
294 public void parseUriParametersDepthParameterNegativeTest() {
295 final UriInfo uriInfo = Mockito.mock(UriInfo.class);
296 final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
298 // inserted value is not allowed
299 parameters.put("depth", Collections.singletonList("bounded"));
300 when(uriInfo.getQueryParameters()).thenReturn(parameters);
303 ReadDataTransactionUtil.parseUriParameters(context, uriInfo);
304 fail("Test expected to fail due to not allowed parameter value");
305 } catch (final RestconfDocumentedException e) {
307 assertEquals("Error type is not correct", ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
308 assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
309 assertEquals("Error status code is not correct", 400, e.getErrors().get(0).getErrorTag().getStatusCode());
314 * Negative test of parsing request URI parameters when depth parameter has not allowed value (less than minimum).
317 public void parseUriParametersDepthMinimalParameterNegativeTest() {
318 final UriInfo uriInfo = Mockito.mock(UriInfo.class);
319 final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
321 // inserted value is too low
323 "depth", Collections.singletonList(String.valueOf(RestconfDataServiceConstant.ReadData.MIN_DEPTH - 1)));
324 when(uriInfo.getQueryParameters()).thenReturn(parameters);
327 ReadDataTransactionUtil.parseUriParameters(context, uriInfo);
328 fail("Test expected to fail due to not allowed parameter value");
329 } catch (final RestconfDocumentedException e) {
331 assertEquals("Error type is not correct", ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
332 assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
333 assertEquals("Error status code is not correct", 400, e.getErrors().get(0).getErrorTag().getStatusCode());
338 * Negative test of parsing request URI parameters when depth parameter has not allowed value (more than maximum).
341 public void parseUriParametersDepthMaximalParameterNegativeTest() {
342 final UriInfo uriInfo = Mockito.mock(UriInfo.class);
343 final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
345 // inserted value is too high
347 "depth", Collections.singletonList(String.valueOf(RestconfDataServiceConstant.ReadData.MAX_DEPTH + 1)));
348 when(uriInfo.getQueryParameters()).thenReturn(parameters);
351 ReadDataTransactionUtil.parseUriParameters(context, uriInfo);
352 fail("Test expected to fail due to not allowed parameter value");
353 } catch (final RestconfDocumentedException e) {
355 assertEquals("Error type is not correct", ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
356 assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
357 assertEquals("Error status code is not correct", 400, e.getErrors().get(0).getErrorTag().getStatusCode());