blob: d2f4c86a3883dee0368ce9e8d8da20f43b14a324 [file] [log] [blame]
Jian Lic134c7a2017-04-25 12:51:28 +09001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Jian Lic134c7a2017-04-25 12:51:28 +09003 *
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.mapping.web;
17
18import com.eclipsesource.json.Json;
19import com.eclipsesource.json.JsonArray;
20import com.eclipsesource.json.JsonObject;
21import com.google.common.collect.ImmutableSet;
22import com.google.common.collect.Maps;
23import com.google.common.collect.Sets;
24import org.glassfish.jersey.server.ResourceConfig;
25import org.hamcrest.Description;
26import org.hamcrest.TypeSafeMatcher;
27import org.junit.After;
28import org.junit.Before;
29import org.junit.Test;
30import org.onlab.osgi.ServiceDirectory;
31import org.onlab.osgi.TestServiceDirectory;
32import org.onlab.packet.IpPrefix;
33import org.onlab.rest.BaseResource;
34import org.onosproject.codec.CodecService;
35import org.onosproject.codec.impl.CodecManager;
36import org.onosproject.mapping.DefaultMappingKey;
37import org.onosproject.mapping.DefaultMappingTreatment;
38import org.onosproject.mapping.DefaultMappingValue;
39import org.onosproject.mapping.MappingEntry;
40import org.onosproject.mapping.MappingId;
41import org.onosproject.mapping.MappingKey;
42import org.onosproject.mapping.MappingService;
43import org.onosproject.mapping.MappingTreatment;
44import org.onosproject.mapping.MappingValue;
45import org.onosproject.mapping.actions.MappingAction;
46import org.onosproject.mapping.actions.MappingActions;
47import org.onosproject.mapping.addresses.MappingAddress;
48import org.onosproject.mapping.addresses.MappingAddresses;
49import org.onosproject.mapping.codec.MappingActionCodec;
50import org.onosproject.mapping.codec.MappingAddressCodec;
51import org.onosproject.mapping.codec.MappingEntryCodec;
52import org.onosproject.mapping.codec.MappingInstructionCodec;
53import org.onosproject.mapping.codec.MappingKeyCodec;
54import org.onosproject.mapping.codec.MappingTreatmentCodec;
55import org.onosproject.mapping.codec.MappingValueCodec;
56import org.onosproject.mapping.instructions.MappingInstruction;
Jian Lia23f46d2017-05-02 18:07:31 +090057import org.onosproject.mapping.web.api.MappingsWebApplication;
Jian Lic134c7a2017-04-25 12:51:28 +090058import org.onosproject.net.DefaultDevice;
59import org.onosproject.net.Device;
60import org.onosproject.net.DeviceId;
61import org.onosproject.net.device.DeviceService;
62import org.onosproject.rest.resources.ResourceTest;
63
64import javax.ws.rs.client.WebTarget;
65import java.util.Map;
66import java.util.Set;
67
68import static org.easymock.EasyMock.anyObject;
69import static org.easymock.EasyMock.createMock;
70import static org.easymock.EasyMock.expect;
71import static org.easymock.EasyMock.replay;
72import static org.easymock.EasyMock.verify;
73import static org.hamcrest.Matchers.hasSize;
74import static org.hamcrest.Matchers.is;
75import static org.hamcrest.Matchers.notNullValue;
76import static org.junit.Assert.assertThat;
77import static org.onosproject.mapping.MappingStore.Type.MAP_DATABASE;
78import static org.onosproject.mapping.instructions.MappingInstructions.multicastPriority;
79import static org.onosproject.mapping.instructions.MappingInstructions.multicastWeight;
80import static org.onosproject.mapping.instructions.MappingInstructions.unicastPriority;
81import static org.onosproject.mapping.instructions.MappingInstructions.unicastWeight;
82
83/**
84 * Unit tests for Mappings REST APIs.
85 */
86public class MappingsWebResourceTest extends ResourceTest {
87
88 private static final String IPV4_STRING_1 = "1.2.3.4";
89 private static final String IPV4_STRING_2 = "5.6.7.8";
90 private static final String PORT_STRING = "32";
91 private static final IpPrefix IPV4_PREFIX_1 =
92 IpPrefix.valueOf(IPV4_STRING_1 + "/" + PORT_STRING);
93 private static final IpPrefix IPV4_PREFIX_2 =
94 IpPrefix.valueOf(IPV4_STRING_2 + "/" + PORT_STRING);
95
96 private static final int UNICAST_WEIGHT = 1;
97 private static final int UNICAST_PRIORITY = 1;
98 private static final int MULTICAST_WEIGHT = 2;
99 private static final int MULTICAST_PRIORITY = 2;
100
101 private static final int DIFF_VALUE = 99;
102
103 private static final String ID = "id";
Jian Li6e960ef2017-05-03 16:38:19 +0900104 private static final String DATABASE = "database";
Jian Lic134c7a2017-04-25 12:51:28 +0900105
106 private static final String PREFIX = "mappings";
107
108 private final MappingService mockMappingService = createMock(MappingService.class);
109
110 private final Map<DeviceId, Set<MappingEntry>> mappings = Maps.newHashMap();
111
112 private final DeviceService mockDeviceService = createMock(DeviceService.class);
113 private final DeviceId deviceId1 = DeviceId.deviceId("1");
114 private final DeviceId deviceId2 = DeviceId.deviceId("2");
115 private final Device device1 = new DefaultDevice(null, deviceId1, Device.Type.ROUTER,
116 "", "", "", "", null);
117 private final Device device2 = new DefaultDevice(null, deviceId2, Device.Type.ROUTER,
118 "", "", "", "", null);
119
120 private final MockMappingEntry mapping1 = new MockMappingEntry(deviceId1, 1);
121 private final MockMappingEntry mapping2 = new MockMappingEntry(deviceId1, 2);
122
123 private final MockMappingEntry mapping3 = new MockMappingEntry(deviceId2, 3);
124 private final MockMappingEntry mapping4 = new MockMappingEntry(deviceId2, 4);
125
126 private final Set<MappingEntry> mappingEntries = ImmutableSet.of(mapping1, mapping2, mapping3, mapping4);
127
128 /**
129 * Constructs a mappings web resource test instance.
130 */
131 public MappingsWebResourceTest() {
132 super(ResourceConfig.forApplicationClass(MappingsWebApplication.class));
133 }
134
135 /**
136 * Mock class for a mapping entry.
137 */
138 private static class MockMappingEntry implements MappingEntry {
Yuta HIGUCHIf7089102017-05-03 10:31:46 -0700139 static final short UNIQUE_SHORT = 2;
Jian Lic134c7a2017-04-25 12:51:28 +0900140 final DeviceId deviceId;
141 MappingKey key;
142 MappingValue value;
143 final long baseValue;
144
145 MockMappingEntry(DeviceId deviceId, long id) {
146 this.deviceId = deviceId;
147 this.baseValue = id * 100;
148 }
149
150 @Override
151 public MappingId id() {
152 final long id = baseValue + 11;
153 return MappingId.valueOf(id);
154 }
155
156 @Override
157 public short appId() {
158 return UNIQUE_SHORT;
159 }
160
161 @Override
162 public DeviceId deviceId() {
163 return deviceId;
164 }
165
166 @Override
167 public MappingKey key() {
168 return key;
169 }
170
171 @Override
172 public MappingValue value() {
173 return value;
174 }
175
176 @Override
177 public MappingEntryState state() {
178 return MappingEntryState.ADDED;
179 }
180 }
181
182 /**
183 * Populates some mappings used as testing data.
184 */
185 private void setupMockMappings() {
186 MappingAddress address1 = MappingAddresses.ipv4MappingAddress(IPV4_PREFIX_1);
187 MappingAddress address2 = MappingAddresses.ipv4MappingAddress(IPV4_PREFIX_2);
188
189 MappingInstruction unicastWeight1 = unicastWeight(UNICAST_WEIGHT);
190 MappingInstruction unicastPriority1 = unicastPriority(UNICAST_PRIORITY);
191 MappingInstruction multicastWeight1 = multicastWeight(MULTICAST_WEIGHT);
192 MappingInstruction multicastPriority1 = multicastPriority(MULTICAST_PRIORITY);
193
194 MappingInstruction unicastWeight2 = unicastWeight(UNICAST_WEIGHT + DIFF_VALUE);
195 MappingInstruction unicastPriority2 = unicastPriority(UNICAST_PRIORITY + DIFF_VALUE);
196 MappingInstruction multicastWeight2 = multicastWeight(MULTICAST_WEIGHT + DIFF_VALUE);
197 MappingInstruction multicastPriority2 = multicastPriority(MULTICAST_PRIORITY + DIFF_VALUE);
198
199 MappingKey key1 = DefaultMappingKey.builder()
200 .withAddress(address1)
201 .build();
202
203 MappingTreatment treatment1 = DefaultMappingTreatment.builder()
204 .add(unicastWeight1)
205 .add(unicastPriority1)
206 .add(multicastWeight1)
207 .add(multicastPriority1)
208 .withAddress(address1)
209 .build();
210
211 MappingAction action1 = MappingActions.noAction();
212
213 MappingValue value1 = DefaultMappingValue.builder()
214 .add(treatment1)
215 .withAction(action1)
216 .build();
217
218 MappingKey key2 = DefaultMappingKey.builder()
219 .withAddress(address2)
220 .build();
221
222 MappingTreatment treatment2 = DefaultMappingTreatment.builder()
223 .add(unicastWeight2)
224 .add(unicastPriority2)
225 .add(multicastWeight2)
226 .add(multicastPriority2)
227 .withAddress(address2)
228 .build();
229
230 MappingAction action2 = MappingActions.forward();
231
232 MappingValue value2 = DefaultMappingValue.builder()
233 .add(treatment2)
234 .withAction(action2)
235 .build();
236
237 mapping1.key = key1;
238 mapping2.key = key2;
239 mapping3.key = key1;
240 mapping4.key = key2;
241
242 mapping1.value = value1;
243 mapping2.value = value2;
244 mapping3.value = value1;
245 mapping4.value = value2;
246
247 final Set<MappingEntry> mappings1 = Sets.newHashSet();
248 mappings1.add(mapping1);
249 mappings1.add(mapping2);
250
251 final Set<MappingEntry> mappings2 = Sets.newHashSet();
252 mappings2.add(mapping3);
253 mappings2.add(mapping4);
254
255 mappings.put(deviceId1, mappings1);
256 mappings.put(deviceId2, mappings2);
257 }
258
259 /**
260 * Sets up the global values for all the tests.
261 */
262 @Before
263 public void setUpTest() {
264
265 // Register the services needed for the test
266 final CodecManager codecService = new CodecManager();
267 codecService.activate();
268 codecService.registerCodec(MappingEntry.class, new MappingEntryCodec());
269 codecService.registerCodec(MappingAddress.class, new MappingAddressCodec());
270 codecService.registerCodec(MappingInstruction.class, new MappingInstructionCodec());
271 codecService.registerCodec(MappingAction.class, new MappingActionCodec());
272 codecService.registerCodec(MappingTreatment.class, new MappingTreatmentCodec());
273 codecService.registerCodec(MappingKey.class, new MappingKeyCodec());
274 codecService.registerCodec(MappingValue.class, new MappingValueCodec());
275 ServiceDirectory testDirectory =
276 new TestServiceDirectory()
277 .add(MappingService.class, mockMappingService)
278 .add(DeviceService.class, mockDeviceService)
279 .add(CodecService.class, codecService);
280
281 BaseResource.setServiceDirectory(testDirectory);
282 }
283
284 /**
285 * Cleans up and verifies the mocks.
286 */
287 @After
288 public void tearDownTest() {
289 verify(mockMappingService);
290 }
291
292 public static class MappingEntryJsonArrayMatcher extends TypeSafeMatcher<JsonArray> {
293
294 private final MappingEntry mapping;
295 private String reason = "";
296
297 MappingEntryJsonArrayMatcher(MappingEntry mappingValue) {
298 mapping = mappingValue;
299 }
300
301 @Override
302 protected boolean matchesSafely(JsonArray json) {
303
304 boolean mappingFound = false;
305
306 for (int jsonMappingIndex = 0; jsonMappingIndex < json.size();
307 jsonMappingIndex++) {
308
309 final JsonObject jsonMapping = json.get(jsonMappingIndex).asObject();
310
311 final String mappingId = Long.toString(mapping.id().value());
312 final String jsonMappingId = jsonMapping.get(ID).asString();
313 if (jsonMappingId.equals(mappingId)) {
314 mappingFound = true;
315 assertThat(jsonMapping, matchesMapping(mapping));
316 }
317 }
318
319 if (!mappingFound) {
320 reason = "Mapping with id " + mapping.id().toString() + " not found";
321 return false;
322 } else {
323 return true;
324 }
325 }
326
327 @Override
328 public void describeTo(Description description) {
329 description.appendText(reason);
330 }
331 }
332
333 /**
334 * Hamcrest matcher for mapping entry.
335 */
336 public static final class MappingEntryJsonMatcher
337 extends TypeSafeMatcher<JsonObject> {
338
339 private final MappingEntry mappingEntry;
340 private String reason = "";
341
342 /**
343 * A default constructor.
344 *
345 * @param mappingEntry mapping entry
346 */
347 private MappingEntryJsonMatcher(MappingEntry mappingEntry) {
348 this.mappingEntry = mappingEntry;
349 }
350
351 @Override
352 protected boolean matchesSafely(JsonObject jsonObject) {
353 // check mapping id
354 final String jsonId = jsonObject.get("id").asString();
355 final String mappingId = Long.toString(mappingEntry.id().value());
356
357 if (!jsonId.equals(mappingId)) {
358 reason = "id " + mappingEntry.id().toString();
359 return false;
360 }
361
362 // check device id
363 final String jsonDeviceId = jsonObject.get("deviceId").asString();
364 final String deviceId = mappingEntry.deviceId().toString();
365 if (!jsonDeviceId.equals(deviceId)) {
366 reason = "deviceId " + mappingEntry.deviceId();
367 return false;
368 }
369
370 // check state
371 final String jsonState = jsonObject.get("state").asString();
372 final String state = mappingEntry.state().name();
373 if (!jsonState.equals(state)) {
374 reason = "state " + mappingEntry.state().name();
375 return false;
376 }
377
378 return true;
379 }
380
381 @Override
382 public void describeTo(Description description) {
383 description.appendText(reason);
384 }
385 }
386
387 /**
388 * Factory to allocate a mapping matcher.
389 *
390 * @param mapping mapping object we are looking for
391 * @return matcher
392 */
393 private static MappingEntryJsonMatcher matchesMapping(MappingEntry mapping) {
394 return new MappingEntryJsonMatcher(mapping);
395 }
396
397 /**
398 * Factory to allocate a mapping array matcher.
399 *
400 * @param mapping mapping object we are looking for
401 * @return matcher
402 */
403 private static MappingEntryJsonArrayMatcher hasMapping(MappingEntry mapping) {
404 return new MappingEntryJsonArrayMatcher(mapping);
405 }
406
407 /**
408 * Tests the result of the rest api GET when there are no mappings.
409 */
410 @Test
411 public void testMappingsEmptyArray() {
412 expect(mockMappingService.getAllMappingEntries(anyObject()))
413 .andReturn(null).anyTimes();
414 replay(mockMappingService);
415 final WebTarget wt = target();
Jian Li6e960ef2017-05-03 16:38:19 +0900416 final String response = wt.path(PREFIX + "/" + DATABASE).request().get(String.class);
Jian Lic134c7a2017-04-25 12:51:28 +0900417 assertThat(response, is("{\"mappings\":[]}"));
418 }
419
420 /**
421 * Tests the result of the rest api GET when there are active mappings.
422 */
423 @Test
424 public void testMappingsPopulateArray() {
425 setupMockMappings();
426 expect(mockMappingService.getAllMappingEntries(anyObject()))
427 .andReturn(mappingEntries).once();
428 replay(mockMappingService);
429 final WebTarget wt = target();
Jian Li6e960ef2017-05-03 16:38:19 +0900430 final String response = wt.path(PREFIX + "/" + DATABASE).request().get(String.class);
Jian Lic134c7a2017-04-25 12:51:28 +0900431 final JsonObject result = Json.parse(response).asObject();
432 assertThat(result, notNullValue());
433
434 assertThat(result.names(), hasSize(1));
435 assertThat(result.names().get(0), is("mappings"));
436 final JsonArray jsonMappings = result.get("mappings").asArray();
437 assertThat(jsonMappings, notNullValue());
438 assertThat(jsonMappings, hasMapping(mapping1));
439 assertThat(jsonMappings, hasMapping(mapping2));
440 assertThat(jsonMappings, hasMapping(mapping3));
441 assertThat(jsonMappings, hasMapping(mapping4));
442 }
443
444 /**
445 * Tests the result of the rest api GET with a device ID when there are
446 * no mappings.
447 */
448 @Test
449 public void testMappingsByDevIdEmptyArray() {
450 expect(mockDeviceService.getDevice(deviceId1)).andReturn(device1);
451 expect(mockMappingService.getMappingEntries(MAP_DATABASE, deviceId1))
452 .andReturn(null).anyTimes();
453 replay(mockDeviceService);
454 replay(mockMappingService);
455
456 final WebTarget wt = target();
Jian Li6e960ef2017-05-03 16:38:19 +0900457 final String response = wt.path(PREFIX + "/" + deviceId1 + "/" + DATABASE)
Jian Lic134c7a2017-04-25 12:51:28 +0900458 .request().get(String.class);
459 assertThat(response, is("{\"mappings\":[]}"));
460 }
461
462 /**
463 * Tests the result of the rest api GET with a device ID when there are
464 * active mappings.
465 */
466 @Test
467 public void testMappingsByDevIdPopulateArray() {
468 setupMockMappings();
469 expect(mockDeviceService.getDevice(deviceId2)).andReturn(device2);
470 expect(mockMappingService.getMappingEntries(MAP_DATABASE, deviceId2))
471 .andReturn(mappings.get(deviceId2)).once();
472 replay(mockDeviceService);
473 replay(mockMappingService);
474
475 final WebTarget wt = target();
Jian Li6e960ef2017-05-03 16:38:19 +0900476 final String response = wt.path(PREFIX + "/" + deviceId2 + "/" + DATABASE)
Jian Lic134c7a2017-04-25 12:51:28 +0900477 .request().get(String.class);
478
479 final JsonObject result = Json.parse(response).asObject();
480 assertThat(result, notNullValue());
481
482 assertThat(result.names(), hasSize(1));
483 assertThat(result.names().get(0), is("mappings"));
484 final JsonArray jsonMappings = result.get("mappings").asArray();
485 assertThat(jsonMappings, notNullValue());
486 assertThat(jsonMappings, hasMapping(mapping3));
487 assertThat(jsonMappings, hasMapping(mapping4));
488 }
489}