blob: b02e1a6c39d11fc693f78585bb3c781a8a17e05d [file] [log] [blame]
Ray Milkey37a5d8c2015-11-23 09:40:57 -08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
Ray Milkey37a5d8c2015-11-23 09:40:57 -08003 *
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.rest.resources;
17
Ray Milkeyb83797c2017-06-12 15:42:42 -070018import java.io.InputStream;
19import java.net.HttpURLConnection;
20import java.util.HashSet;
21import java.util.Set;
22
23import javax.ws.rs.NotFoundException;
24import javax.ws.rs.client.Entity;
25import javax.ws.rs.client.WebTarget;
26import javax.ws.rs.core.MediaType;
27import javax.ws.rs.core.Response;
28
29import org.eclipse.jetty.http.HttpStatus;
Ray Milkey37a5d8c2015-11-23 09:40:57 -080030import org.junit.Assert;
31import org.junit.Before;
32import org.junit.Test;
33import org.onlab.osgi.ServiceDirectory;
34import org.onlab.osgi.TestServiceDirectory;
35import org.onlab.rest.BaseResource;
36import org.onosproject.net.DefaultDevice;
37import org.onosproject.net.Device;
38import org.onosproject.net.Link;
39import org.onosproject.net.config.Config;
40import org.onosproject.net.config.NetworkConfigService;
41import org.onosproject.net.config.NetworkConfigServiceAdapter;
42import org.onosproject.net.config.SubjectFactory;
Ray Milkey37a5d8c2015-11-23 09:40:57 -080043
Ray Milkeyb83797c2017-06-12 15:42:42 -070044import com.eclipsesource.json.Json;
45import com.eclipsesource.json.JsonObject;
46import com.eclipsesource.json.JsonValue;
47import com.fasterxml.jackson.databind.JsonNode;
48import com.fasterxml.jackson.databind.ObjectMapper;
49import com.google.common.collect.ImmutableSet;
Ray Milkey37a5d8c2015-11-23 09:40:57 -080050
51import static org.easymock.EasyMock.createMock;
52import static org.easymock.EasyMock.replay;
53import static org.hamcrest.MatcherAssert.assertThat;
54import static org.hamcrest.Matchers.containsString;
55import static org.hamcrest.Matchers.hasSize;
56import static org.hamcrest.Matchers.is;
57import static org.hamcrest.Matchers.notNullValue;
58import static org.junit.Assert.fail;
59
60/**
61 * Unit tests for network config web resource.
62 */
63public class NetworkConfigWebResourceTest extends ResourceTest {
64
Ray Milkeyb83797c2017-06-12 15:42:42 -070065 private MockNetworkConfigService mockNetworkConfigService;
Ray Milkey37a5d8c2015-11-23 09:40:57 -080066
67 public class MockDeviceConfig extends Config<Device> {
68
69 final String field1Value;
70 final String field2Value;
71
72 MockDeviceConfig(String value1, String value2) {
73 field1Value = value1;
74 field2Value = value2;
75 }
76
77 @Override
78 public String key() {
79 return "basic";
80 }
81
82 @Override
83 public JsonNode node() {
84 return new ObjectMapper()
85 .createObjectNode()
86 .put("field1", field1Value)
87 .put("field2", field2Value);
88 }
89 }
90
91 /**
92 * Mock config factory for devices.
93 */
94 private final SubjectFactory<Device> mockDevicesSubjectFactory =
95 new SubjectFactory<Device>(Device.class, "devices") {
96 @Override
97 public Device createSubject(String subjectKey) {
98 DefaultDevice device = createMock(DefaultDevice.class);
99 replay(device);
100 return device;
101 }
102
103 @Override
104 public Class<Device> subjectClass() {
105 return Device.class;
106 }
107 };
108
109 /**
110 * Mock config factory for links.
111 */
112 private final SubjectFactory<Link> mockLinksSubjectFactory =
113 new SubjectFactory<Link>(Link.class, "links") {
114 @Override
115 public Link createSubject(String subjectKey) {
116 return null;
117 }
118
119 @Override
120 public Class<Link> subjectClass() {
121 return Link.class;
122 }
123 };
124
125 /**
126 * Mocked config service.
127 */
128 class MockNetworkConfigService extends NetworkConfigServiceAdapter {
129
130 Set devicesSubjects = new HashSet<>();
131 Set devicesConfigs = new HashSet<>();
132 Set linksSubjects = new HashSet();
133 Set linksConfigs = new HashSet<>();
134
135 @Override
136 public Set<Class> getSubjectClasses() {
137 return ImmutableSet.of(Device.class, Link.class);
138 }
139
140 @Override
141 public SubjectFactory getSubjectFactory(Class subjectClass) {
142 if (subjectClass == Device.class) {
143 return mockDevicesSubjectFactory;
144 } else if (subjectClass == Link.class) {
145 return mockLinksSubjectFactory;
146 }
147 return null;
148 }
149
150 @Override
151 public SubjectFactory getSubjectFactory(String subjectClassKey) {
Jon Halla3fcf672017-03-28 16:53:22 -0700152 if ("devices".equals(subjectClassKey)) {
Ray Milkey37a5d8c2015-11-23 09:40:57 -0800153 return mockDevicesSubjectFactory;
Jon Halla3fcf672017-03-28 16:53:22 -0700154 } else if ("links".equals(subjectClassKey)) {
Ray Milkey37a5d8c2015-11-23 09:40:57 -0800155 return mockLinksSubjectFactory;
156 }
157 return null;
158 }
159
160 @SuppressWarnings("unchecked")
161 @Override
162 public <S> Set<S> getSubjects(Class<S> subjectClass) {
163 if (subjectClass == Device.class) {
164 return devicesSubjects;
165 } else if (subjectClass == Link.class) {
166 return linksSubjects;
167 }
168 return null;
169 }
170
171 @SuppressWarnings("unchecked")
172 @Override
173 public <S> Set<? extends Config<S>> getConfigs(S subject) {
174 if (subject instanceof Device || subject.toString().contains("device")) {
175 return devicesConfigs;
176 } else if (subject.toString().contains("link")) {
177 return linksConfigs;
178 }
179 return null;
180 }
181
182 @SuppressWarnings("unchecked")
183 @Override
184 public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
185
186 if (configClass == MockDeviceConfig.class) {
187 return (C) devicesConfigs.toArray()[0];
188 }
189 return null;
190 }
191
192 @Override
193 public Class<? extends Config> getConfigClass(String subjectClassKey, String configKey) {
194 return MockDeviceConfig.class;
195 }
196 }
197
Ray Milkey37a5d8c2015-11-23 09:40:57 -0800198 /**
199 * Sets up mocked config service.
200 */
201 @Before
Jian Li9d616492016-03-09 10:52:49 -0800202 public void setUpMocks() {
Ray Milkey37a5d8c2015-11-23 09:40:57 -0800203 mockNetworkConfigService = new MockNetworkConfigService();
204 ServiceDirectory testDirectory =
205 new TestServiceDirectory()
Thomas Vachuska6f350ed2016-01-08 09:53:03 -0800206 .add(NetworkConfigService.class, mockNetworkConfigService);
Ray Milkey37a5d8c2015-11-23 09:40:57 -0800207 BaseResource.setServiceDirectory(testDirectory);
208 }
209
210 /**
211 * Sets up test config data.
212 */
213 @SuppressWarnings("unchecked")
Ray Milkeyb83797c2017-06-12 15:42:42 -0700214 private void setUpConfigData() {
Ray Milkey37a5d8c2015-11-23 09:40:57 -0800215 mockNetworkConfigService.devicesSubjects.add("device1");
216 mockNetworkConfigService.devicesConfigs.add(new MockDeviceConfig("v1", "v2"));
217 }
218
219 /**
220 * Tests the result of the rest api GET when there are no configs.
221 */
222 @Test
223 public void testEmptyConfigs() {
Jian Li9d616492016-03-09 10:52:49 -0800224 final WebTarget wt = target();
225 final String response = wt.path("network/configuration").request().get(String.class);
Ray Milkey37a5d8c2015-11-23 09:40:57 -0800226
227 assertThat(response, containsString("\"devices\":{}"));
228 assertThat(response, containsString("\"links\":{}"));
229 }
230
231 /**
232 * Tests the result of the rest api GET for a single subject with no configs.
233 */
234 @Test
235 public void testEmptyConfig() {
Jian Li9d616492016-03-09 10:52:49 -0800236 final WebTarget wt = target();
237 final String response = wt.path("network/configuration/devices").request().get(String.class);
Ray Milkey37a5d8c2015-11-23 09:40:57 -0800238
239 assertThat(response, is("{}"));
240 }
241
242 /**
243 * Tests the result of the rest api GET for a single subject that
244 * is undefined.
245 */
246 @Test
247 public void testNonExistentConfig() {
Jian Li9d616492016-03-09 10:52:49 -0800248 final WebTarget wt = target();
Ray Milkey37a5d8c2015-11-23 09:40:57 -0800249
250 try {
Jian Li9d616492016-03-09 10:52:49 -0800251 final String response = wt.path("network/configuration/nosuchkey").request().get(String.class);
Ray Milkey37a5d8c2015-11-23 09:40:57 -0800252 fail("GET of non-existent key does not produce an exception " + response);
Jian Li9d616492016-03-09 10:52:49 -0800253 } catch (NotFoundException e) {
Ray Milkey37a5d8c2015-11-23 09:40:57 -0800254 assertThat(e.getResponse().getStatus(), is(HttpURLConnection.HTTP_NOT_FOUND));
255 }
256 }
257
258 private void checkBasicAttributes(JsonValue basic) {
259 Assert.assertThat(basic.asObject().get("field1").asString(), is("v1"));
260 Assert.assertThat(basic.asObject().get("field2").asString(), is("v2"));
261 }
262
263 /**
264 * Tests the result of the rest api GET when there is a config.
265 */
266 @Test
Ray Milkey37a5d8c2015-11-23 09:40:57 -0800267 public void testConfigs() {
268 setUpConfigData();
Jian Li9d616492016-03-09 10:52:49 -0800269 final WebTarget wt = target();
270 final String response = wt.path("network/configuration").request().get(String.class);
Ray Milkey37a5d8c2015-11-23 09:40:57 -0800271
Jian Li80cfe452016-01-14 16:04:58 -0800272 final JsonObject result = Json.parse(response).asObject();
Ray Milkey37a5d8c2015-11-23 09:40:57 -0800273 Assert.assertThat(result, notNullValue());
274
275 Assert.assertThat(result.names(), hasSize(2));
276
277 JsonValue devices = result.get("devices");
278 Assert.assertThat(devices, notNullValue());
279
280 JsonValue device1 = devices.asObject().get("device1");
281 Assert.assertThat(device1, notNullValue());
282
283 JsonValue basic = device1.asObject().get("basic");
284 Assert.assertThat(basic, notNullValue());
285
286 checkBasicAttributes(basic);
287 }
288
289 /**
290 * Tests the result of the rest api single subject key GET when
291 * there is a config.
292 */
293 @Test
294 public void testSingleSubjectKeyConfig() {
295 setUpConfigData();
Jian Li9d616492016-03-09 10:52:49 -0800296 final WebTarget wt = target();
297 final String response = wt.path("network/configuration/devices").request().get(String.class);
Ray Milkey37a5d8c2015-11-23 09:40:57 -0800298
Jian Li80cfe452016-01-14 16:04:58 -0800299 final JsonObject result = Json.parse(response).asObject();
Ray Milkey37a5d8c2015-11-23 09:40:57 -0800300 Assert.assertThat(result, notNullValue());
301
302 Assert.assertThat(result.names(), hasSize(1));
303
304 JsonValue device1 = result.asObject().get("device1");
305 Assert.assertThat(device1, notNullValue());
306
307 JsonValue basic = device1.asObject().get("basic");
308 Assert.assertThat(basic, notNullValue());
309
310 checkBasicAttributes(basic);
311 }
312
313 /**
314 * Tests the result of the rest api single subject GET when
315 * there is a config.
316 */
317 @Test
318 public void testSingleSubjectConfig() {
319 setUpConfigData();
Jian Li9d616492016-03-09 10:52:49 -0800320 final WebTarget wt = target();
Ray Milkey37a5d8c2015-11-23 09:40:57 -0800321 final String response =
Jian Li9d616492016-03-09 10:52:49 -0800322 wt.path("network/configuration/devices/device1")
323 .request()
Ray Milkey37a5d8c2015-11-23 09:40:57 -0800324 .get(String.class);
325
Jian Li80cfe452016-01-14 16:04:58 -0800326 final JsonObject result = Json.parse(response).asObject();
Ray Milkey37a5d8c2015-11-23 09:40:57 -0800327 Assert.assertThat(result, notNullValue());
328
329 Assert.assertThat(result.names(), hasSize(1));
330
331 JsonValue basic = result.asObject().get("basic");
332 Assert.assertThat(basic, notNullValue());
333
334 checkBasicAttributes(basic);
335 }
336
337 /**
338 * Tests the result of the rest api single subject single config GET when
339 * there is a config.
340 */
341 @Test
342 public void testSingleSubjectSingleConfig() {
343 setUpConfigData();
Jian Li9d616492016-03-09 10:52:49 -0800344 final WebTarget wt = target();
Ray Milkey37a5d8c2015-11-23 09:40:57 -0800345 final String response =
Jian Li9d616492016-03-09 10:52:49 -0800346 wt.path("network/configuration/devices/device1/basic")
347 .request()
Ray Milkey37a5d8c2015-11-23 09:40:57 -0800348 .get(String.class);
349
Jian Li80cfe452016-01-14 16:04:58 -0800350 final JsonObject result = Json.parse(response).asObject();
Ray Milkey37a5d8c2015-11-23 09:40:57 -0800351 Assert.assertThat(result, notNullValue());
352
353 Assert.assertThat(result.names(), hasSize(2));
354
355 checkBasicAttributes(result);
356 }
357
Ray Milkeyb83797c2017-06-12 15:42:42 -0700358 /**
359 * Tests network configuration with POST and illegal JSON.
360 */
361 @Test
362 public void testBadPost() {
363 String json = "this is invalid!";
364 WebTarget wt = target();
365
366 Response response = wt.path("network/configuration")
367 .request(MediaType.APPLICATION_JSON_TYPE)
368 .post(Entity.json(json));
369 Assert.assertThat(response.getStatus(), is(HttpURLConnection.HTTP_BAD_REQUEST));
370 }
371
372 /**
373 * Tests creating a network config with POST.
374 */
375 @Test
376 public void testPost() {
377 InputStream jsonStream = IntentsResourceTest.class
378 .getResourceAsStream("post-config.json");
379 WebTarget wt = target();
380
381 Response response = wt.path("network/configuration")
382 .request(MediaType.APPLICATION_JSON_TYPE)
383 .post(Entity.json(jsonStream));
384 Assert.assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
385 }
386
387 /**
388 * Tests creating a network config with POST of valid but incorrect JSON.
389 */
390 @Test
391 public void testBadSyntaxPost() {
392 InputStream jsonStream = IntentsResourceTest.class
393 .getResourceAsStream("post-config-bad-syntax.json");
394 WebTarget wt = target();
395
396 Response response = wt.path("network/configuration")
397 .request(MediaType.APPLICATION_JSON_TYPE)
398 .post(Entity.json(jsonStream));
399 Assert.assertThat(response.getStatus(), is(HttpStatus.MULTI_STATUS_207));
400 }
401
402 // TODO: Add test for DELETE
Ray Milkey37a5d8c2015-11-23 09:40:57 -0800403}