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.restful.utils;
11 import static org.junit.Assert.assertEquals;
12 import static org.junit.Assert.assertFalse;
13 import static org.junit.Assert.assertNull;
14 import static org.junit.Assert.assertTrue;
15 import static org.junit.Assert.fail;
16 import static org.mockito.Mockito.doReturn;
17 import static org.mockito.Mockito.when;
19 import com.google.common.base.Optional;
20 import com.google.common.util.concurrent.Futures;
21 import java.util.Collections;
22 import javax.ws.rs.core.MultivaluedHashMap;
23 import javax.ws.rs.core.UriInfo;
24 import org.junit.Before;
25 import org.junit.Test;
26 import org.mockito.Mock;
27 import org.mockito.Mockito;
28 import org.mockito.MockitoAnnotations;
29 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
30 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
31 import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
32 import org.opendaylight.netconf.sal.restconf.impl.InstanceIdentifierContext;
33 import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
34 import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorTag;
35 import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorType;
36 import org.opendaylight.netconf.sal.restconf.impl.WriterParameters;
37 import org.opendaylight.restconf.restful.transaction.TransactionVarsWrapper;
38 import org.opendaylight.yangtools.yang.common.QName;
39 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
40 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
41 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
42 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
43 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
45 public class ReadDataTransactionUtilTest {
47 private static final TestData data = new TestData();
48 private static final YangInstanceIdentifier.NodeIdentifier nodeIdentifier = new YangInstanceIdentifier
49 .NodeIdentifier(QName.create("ns", "2016-02-28", "container"));
51 private TransactionVarsWrapper wrapper;
53 private DOMTransactionChain transactionChain;
55 private InstanceIdentifierContext<?> context;
57 private DOMDataReadOnlyTransaction read;
61 MockitoAnnotations.initMocks(this);
63 doReturn(read).when(transactionChain).newReadOnlyTransaction();
64 wrapper = new TransactionVarsWrapper(this.context, null, this.transactionChain);
68 public void readDataConfigTest() {
69 doReturn(Futures.immediateCheckedFuture(Optional.of(data.data3))).when(read)
70 .read(LogicalDatastoreType.CONFIGURATION, data.path);
71 doReturn(data.path).when(context).getInstanceIdentifier();
72 final String valueOfContent = RestconfDataServiceConstant.ReadData.CONFIG;
73 final NormalizedNode<?, ?> normalizedNode = ReadDataTransactionUtil.readData(valueOfContent, wrapper);
74 assertEquals(data.data3, normalizedNode);
78 public void readAllHavingOnlyConfigTest() {
79 doReturn(Futures.immediateCheckedFuture(Optional.of(data.data3))).when(read)
80 .read(LogicalDatastoreType.CONFIGURATION, data.path);
81 doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(read)
82 .read(LogicalDatastoreType.OPERATIONAL, data.path);
83 doReturn(data.path).when(context).getInstanceIdentifier();
84 final String valueOfContent = RestconfDataServiceConstant.ReadData.ALL;
85 final NormalizedNode<?, ?> normalizedNode = ReadDataTransactionUtil.readData(valueOfContent, wrapper);
86 assertEquals(data.data3, normalizedNode);
90 public void readAllHavingOnlyNonConfigTest() {
91 doReturn(Futures.immediateCheckedFuture(Optional.of(data.data2))).when(read)
92 .read(LogicalDatastoreType.OPERATIONAL, data.path2);
93 doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(read)
94 .read(LogicalDatastoreType.CONFIGURATION, data.path2);
95 doReturn(data.path2).when(context).getInstanceIdentifier();
96 final String valueOfContent = RestconfDataServiceConstant.ReadData.ALL;
97 final NormalizedNode<?, ?> normalizedNode = ReadDataTransactionUtil.readData(valueOfContent, wrapper);
98 assertEquals(data.data2, normalizedNode);
102 public void readDataNonConfigTest() {
103 doReturn(Futures.immediateCheckedFuture(Optional.of(data.data2))).when(read)
104 .read(LogicalDatastoreType.OPERATIONAL, data.path2);
105 doReturn(data.path2).when(context).getInstanceIdentifier();
106 final String valueOfContent = RestconfDataServiceConstant.ReadData.NONCONFIG;
107 final NormalizedNode<?, ?> normalizedNode = ReadDataTransactionUtil.readData(valueOfContent, wrapper);
108 assertEquals(data.data2, normalizedNode);
112 public void readContainerDataAllTest() {
113 doReturn(Futures.immediateCheckedFuture(Optional.of(data.data3))).when(read)
114 .read(LogicalDatastoreType.CONFIGURATION, data.path);
115 doReturn(Futures.immediateCheckedFuture(Optional.of(data.data4))).when(read)
116 .read(LogicalDatastoreType.OPERATIONAL, data.path);
117 doReturn(data.path).when(context).getInstanceIdentifier();
118 final String valueOfContent = RestconfDataServiceConstant.ReadData.ALL;
119 final NormalizedNode<?, ?> normalizedNode = ReadDataTransactionUtil.readData(valueOfContent, wrapper);
120 final ContainerNode checkingData = Builders
122 .withNodeIdentifier(nodeIdentifier)
123 .withChild(data.contentLeaf)
124 .withChild(data.contentLeaf2)
126 assertEquals(checkingData, normalizedNode);
130 public void readContainerDataConfigNoValueOfContentTest() {
131 doReturn(Futures.immediateCheckedFuture(Optional.of(data.data3))).when(read)
132 .read(LogicalDatastoreType.CONFIGURATION, data.path);
133 doReturn(Futures.immediateCheckedFuture(Optional.of(data.data4))).when(read)
134 .read(LogicalDatastoreType.OPERATIONAL, data.path);
135 doReturn(data.path).when(context).getInstanceIdentifier();
136 final NormalizedNode<?, ?> normalizedNode = ReadDataTransactionUtil.readData(
137 RestconfDataServiceConstant.ReadData.ALL, wrapper);
138 final ContainerNode checkingData = Builders
140 .withNodeIdentifier(nodeIdentifier)
141 .withChild(data.contentLeaf)
142 .withChild(data.contentLeaf2)
144 assertEquals(checkingData, normalizedNode);
148 public void readListDataAllTest() {
149 doReturn(Futures.immediateCheckedFuture(Optional.of(data.listData))).when(read)
150 .read(LogicalDatastoreType.OPERATIONAL, data.path3);
151 doReturn(Futures.immediateCheckedFuture(Optional.of(data.listData2))).when(read)
152 .read(LogicalDatastoreType.CONFIGURATION, data.path3);
153 doReturn(data.path3).when(context).getInstanceIdentifier();
154 final String valueOfContent = RestconfDataServiceConstant.ReadData.ALL;
155 final NormalizedNode<?, ?> normalizedNode = ReadDataTransactionUtil.readData(valueOfContent, wrapper);
156 final MapNode checkingData = Builders
158 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(QName.create("ns", "2016-02-28", "list")))
159 .withChild(data.checkData)
161 assertEquals(checkingData, normalizedNode);
165 public void readDataWrongPathOrNoContentTest() {
166 doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(read)
167 .read(LogicalDatastoreType.CONFIGURATION, data.path2);
168 doReturn(data.path2).when(context).getInstanceIdentifier();
169 final String valueOfContent = RestconfDataServiceConstant.ReadData.CONFIG;
170 final NormalizedNode<?, ?> normalizedNode = ReadDataTransactionUtil.readData(valueOfContent, wrapper);
171 assertNull(normalizedNode);
174 @Test(expected = RestconfDocumentedException.class)
175 public void readDataFailTest() {
176 final String valueOfContent = RestconfDataServiceConstant.ReadData.READ_TYPE_TX;
177 final NormalizedNode<?, ?> normalizedNode = ReadDataTransactionUtil.readData(valueOfContent, null);
178 assertNull(normalizedNode);
182 * Test of parsing default parameters from URI request
185 public void parseUriParametersDefaultTest() {
186 final UriInfo uriInfo = Mockito.mock(UriInfo.class);
187 final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
189 // no parameters, default values should be used
190 when(uriInfo.getQueryParameters()).thenReturn(parameters);
192 final WriterParameters parsedParameters = ReadDataTransactionUtil.parseUriParameters(uriInfo);
194 assertEquals("Not correctly parsed URI parameter",
195 RestconfDataServiceConstant.ReadData.ALL, parsedParameters.getContent());
196 assertFalse("Not correctly parsed URI parameter",
197 parsedParameters.getDepth().isPresent());
201 * Test of parsing user defined parameters from URI request
204 public void parseUriParametersUserDefinedTest() {
205 final UriInfo uriInfo = Mockito.mock(UriInfo.class);
206 final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
208 final String content = "config";
209 final String depth = "10";
211 parameters.put("content", Collections.singletonList(content));
212 parameters.put("depth", Collections.singletonList(depth));
214 when(uriInfo.getQueryParameters()).thenReturn(parameters);
216 final WriterParameters parsedParameters = ReadDataTransactionUtil.parseUriParameters(uriInfo);
218 assertEquals("Not correctly parsed URI parameter",
219 content, parsedParameters.getContent());
220 assertTrue("Not correctly parsed URI parameter",
221 parsedParameters.getDepth().isPresent());
222 assertEquals("Not correctly parsed URI parameter",
223 depth, parsedParameters.getDepth().get().toString());
227 * Negative test of parsing request URI parameters when content parameter has not allowed value.
230 public void parseUriParametersContentParameterNegativeTest() {
231 final UriInfo uriInfo = Mockito.mock(UriInfo.class);
232 final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
234 parameters.put("content", Collections.singletonList("not-allowed-parameter-value"));
235 when(uriInfo.getQueryParameters()).thenReturn(parameters);
238 ReadDataTransactionUtil.parseUriParameters(uriInfo);
239 fail("Test expected to fail due to not allowed parameter value");
240 } catch (final RestconfDocumentedException e) {
242 assertEquals("Error type is not correct", ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
243 assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
244 assertEquals("Error status code is not correct", 400, e.getErrors().get(0).getErrorTag().getStatusCode());
249 * Negative test of parsing request URI parameters when depth parameter has not allowed value.
252 public void parseUriParametersDepthParameterNegativeTest() {
253 final UriInfo uriInfo = Mockito.mock(UriInfo.class);
254 final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
256 // inserted value is not allowed
257 parameters.put("depth", Collections.singletonList("bounded"));
258 when(uriInfo.getQueryParameters()).thenReturn(parameters);
261 ReadDataTransactionUtil.parseUriParameters(uriInfo);
262 fail("Test expected to fail due to not allowed parameter value");
263 } catch (final RestconfDocumentedException e) {
265 assertEquals("Error type is not correct", ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
266 assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
267 assertEquals("Error status code is not correct", 400, e.getErrors().get(0).getErrorTag().getStatusCode());
272 * Negative test of parsing request URI parameters when depth parameter has not allowed value (less than minimum).
275 public void parseUriParametersDepthMinimalParameterNegativeTest() {
276 final UriInfo uriInfo = Mockito.mock(UriInfo.class);
277 final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
279 // inserted value is too low
281 "depth", Collections.singletonList(String.valueOf(RestconfDataServiceConstant.ReadData.MIN_DEPTH - 1)));
282 when(uriInfo.getQueryParameters()).thenReturn(parameters);
285 ReadDataTransactionUtil.parseUriParameters(uriInfo);
286 fail("Test expected to fail due to not allowed parameter value");
287 } catch (final RestconfDocumentedException e) {
289 assertEquals("Error type is not correct", ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
290 assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
291 assertEquals("Error status code is not correct", 400, e.getErrors().get(0).getErrorTag().getStatusCode());
296 * Negative test of parsing request URI parameters when depth parameter has not allowed value (more than maximum).
299 public void parseUriParametersDepthMaximalParameterNegativeTest() {
300 final UriInfo uriInfo = Mockito.mock(UriInfo.class);
301 final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
303 // inserted value is too high
305 "depth", Collections.singletonList(String.valueOf(RestconfDataServiceConstant.ReadData.MAX_DEPTH + 1)));
306 when(uriInfo.getQueryParameters()).thenReturn(parameters);
309 ReadDataTransactionUtil.parseUriParameters(uriInfo);
310 fail("Test expected to fail due to not allowed parameter value");
311 } catch (final RestconfDocumentedException e) {
313 assertEquals("Error type is not correct", ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
314 assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
315 assertEquals("Error status code is not correct", 400, e.getErrors().get(0).getErrorTag().getStatusCode());