blob: 603bbf66366ff359bf14b9040cb1f88e3305ef9f [file] [log] [blame]
Sean Condon13b16812018-01-25 10:31:49 +00001/*
2 * Copyright 2017-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.protocol.restconf.server.rpp;
17
18
19import com.fasterxml.jackson.databind.ObjectMapper;
20import com.fasterxml.jackson.databind.node.ObjectNode;
21import org.easymock.EasyMock;
22import org.glassfish.jersey.server.ResourceConfig;
23import org.junit.Before;
24import org.junit.Test;
25import org.onlab.osgi.ServiceDirectory;
26import org.onlab.osgi.TestServiceDirectory;
27import org.onosproject.rest.resources.ResourceTest;
28import org.onosproject.restconf.api.RestconfError;
29import org.onosproject.restconf.api.RestconfException;
30import org.onosproject.restconf.api.RestconfService;
31
32import javax.ws.rs.InternalServerErrorException;
33import javax.ws.rs.NotFoundException;
34import javax.ws.rs.client.Entity;
35import javax.ws.rs.client.WebTarget;
36import javax.ws.rs.core.Response;
37
38import java.io.ByteArrayInputStream;
39import java.net.URI;
40import java.nio.charset.StandardCharsets;
41import java.util.Optional;
42import java.util.regex.Matcher;
43import java.util.regex.Pattern;
44
45import static javax.ws.rs.core.Response.Status.CONFLICT;
46import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR;
47import static junit.framework.TestCase.assertTrue;
48import static junit.framework.TestCase.fail;
49import static org.easymock.EasyMock.*;
50import static org.junit.Assert.assertEquals;
51import static org.junit.Assert.assertNotNull;
52
53/**
54 * Test the RestconfWebResource.
55 */
56public class RestconfWebResourceTest extends ResourceTest {
57
58 public static final String DATA_IETF_SYSTEM_SYSTEM = "data/ietf-system:system";
59
60 private static final Pattern RESTCONF_ERROR_REGEXP =
61 Pattern.compile("(\\{\"ietf-restconf:errors\":\\[)\\R?"
62 + "((\\{\"error\":)\\R?"
63 + "(\\{\"error-type\":\")((protocol)|(transport)|(rpc)|(application))(\",)\\R?"
64 + "(\"error-tag\":\")[a-z\\-]*(\",)\\R?"
65 + "((\"error-app-tag\":\").*(\",))?\\R?"
66 + "((\"error-path\":\").*(\",))?\\R?"
67 + "((\"error-message\":\").*(\"))?(\\}\\},?))*(\\]\\})", Pattern.DOTALL);
68
69 private RestconfService restconfService = createMock(RestconfService.class);
70
71 public RestconfWebResourceTest() {
72 super(ResourceConfig.forApplicationClass(RestconfProtocolProxy.class));
73 }
74
75 @Before
76 public void setup() {
77 ServiceDirectory testDirectory = new TestServiceDirectory()
78 .add(RestconfService.class, restconfService);
79 setServiceDirectory(testDirectory);
80 }
81
82 /**
83 * Test handleGetRequest when an Json object is returned.
84 */
85 @Test
86 public void testHandleGetRequest() {
87 ObjectMapper mapper = new ObjectMapper();
88 ObjectNode node = mapper.createObjectNode();
89 expect(restconfService
90 .runGetOperationOnDataResource(URI.create(getBaseUri() + DATA_IETF_SYSTEM_SYSTEM)))
91 .andReturn(node).anyTimes();
92 replay(restconfService);
93
94 WebTarget wt = target();
95 String response = wt.path("/" + DATA_IETF_SYSTEM_SYSTEM).request().get(String.class);
96 assertNotNull(response);
97 }
98
99 /**
100 * Test handleGetRequest when nothing is returned.
101 */
102 @Test
103 public void testHandleGetRequestNotFound() {
104 expect(restconfService
105 .runGetOperationOnDataResource(URI.create(getBaseUri() + DATA_IETF_SYSTEM_SYSTEM)))
106 .andReturn(null).anyTimes();
107 replay(restconfService);
108
109 WebTarget wt = target();
110 try {
111 String response = wt.path("/" + DATA_IETF_SYSTEM_SYSTEM).request().get(String.class);
112 fail("Expecting fail as response is none");
113 } catch (NotFoundException e) {
114 assertNotNull(e.getResponse());
115 assertRestconfErrorJson(e.getResponse());
116 }
117 }
118
119 /**
120 * Test handleGetRequest when an RestconfException is thrown.
121 */
122 @Test
123 public void testHandleGetRequestRestconfException() {
124 expect(restconfService
125 .runGetOperationOnDataResource(URI.create(getBaseUri() + DATA_IETF_SYSTEM_SYSTEM)))
126 .andThrow(new RestconfException("Suitable error message",
127 RestconfError.ErrorTag.OPERATION_FAILED, INTERNAL_SERVER_ERROR,
128 Optional.of("/" + DATA_IETF_SYSTEM_SYSTEM),
129 Optional.of("More info about the error")))
130 .anyTimes();
131 replay(restconfService);
132
133 WebTarget wt = target();
134 try {
135 String response = wt.path("/" + DATA_IETF_SYSTEM_SYSTEM).request().get(String.class);
136 fail("Expecting fail as response is RestconfException");
137 } catch (InternalServerErrorException e) {
138 assertNotNull(e.getResponse());
139 assertRestconfErrorJson(e.getResponse());
140 }
141 }
142
143 /**
144 * Test handleGetRequest when an Exception is thrown.
145 */
146 @Test
147 public void testHandleGetRequestIoException() {
148 expect(restconfService
149 .runGetOperationOnDataResource(URI.create(getBaseUri() + DATA_IETF_SYSTEM_SYSTEM)))
150 .andThrow(new IllegalArgumentException("A test exception"))
151 .anyTimes();
152 replay(restconfService);
153
154 WebTarget wt = target();
155 try {
156 String response = wt.path("/" + DATA_IETF_SYSTEM_SYSTEM).request().get(String.class);
157 fail("Expecting fail as response is IllegalArgumentException");
158 } catch (InternalServerErrorException e) {
159 assertNotNull(e.getResponse());
160 assertRestconfErrorJson(e.getResponse());
161 }
162 }
163
164 /**
165 * Test handlePostRequest with no exception.
166 */
167 @Test
168 public void testHandlePostRequest() {
169 ObjectMapper mapper = new ObjectMapper();
170 ObjectNode ietfSystemSubNode = mapper.createObjectNode();
171 ietfSystemSubNode.put("contact", "Open Networking Foundation");
172 ietfSystemSubNode.put("hostname", "host1");
173 ietfSystemSubNode.put("location", "The moon");
174
175 ObjectNode ietfSystemNode = mapper.createObjectNode();
176 ietfSystemNode.put("ietf-system:system", ietfSystemSubNode);
177
178 WebTarget wt = target();
179 Response response = wt.path("/" + DATA_IETF_SYSTEM_SYSTEM)
180 .request()
181 .post(Entity.json(ietfSystemNode.toString()));
182 assertEquals(201, response.getStatus());
183 }
184
185 /**
186 * Test handlePostRequest with 'already exists' exception.
187 */
188 @Test
189 public void testHandlePostRequestAlreadyExists() {
190 ObjectMapper mapper = new ObjectMapper();
191 ObjectNode ietfSystemSubNode = mapper.createObjectNode();
192 ietfSystemSubNode.put("contact", "Open Networking Foundation");
193 ietfSystemSubNode.put("hostname", "host1");
194 ietfSystemSubNode.put("location", "The moon");
195
196 ObjectNode ietfSystemNode = mapper.createObjectNode();
197 ietfSystemNode.put("ietf-system:system", ietfSystemSubNode);
198
199 restconfService.runPostOperationOnDataResource(
200 EasyMock.<URI>anyObject(), EasyMock.<ObjectNode>anyObject());
201 expectLastCall().andThrow(new RestconfException("Requested node already present", null,
202 RestconfError.ErrorTag.DATA_EXISTS, CONFLICT,
203 Optional.of("/" + DATA_IETF_SYSTEM_SYSTEM)));
204 replay(restconfService);
205
206 WebTarget wt = target();
207 Response response = wt.path("/" + DATA_IETF_SYSTEM_SYSTEM)
208 .request()
209 .post(Entity.json(ietfSystemNode.toString()));
210 assertEquals(409, response.getStatus());
211 }
212
213 private static void assertRestconfErrorJson(Response errorResponse) {
214 ByteArrayInputStream in = (ByteArrayInputStream) errorResponse.getEntity();
215 int n = in.available();
216 byte[] bytes = new byte[n];
217 in.read(bytes, 0, n);
218
219 Matcher m = RESTCONF_ERROR_REGEXP.matcher(new String(bytes, StandardCharsets.UTF_8));
220 assertTrue(m.matches());
221 }
222}