blob: 86cd4471601a3071a668d1928b4b419b01465279 [file] [log] [blame]
Ray Milkey4f5de002014-12-17 19:26:11 -08001/*
Ray Milkey34c95902015-04-15 09:47:53 -07002 * Copyright 2014-2015 Open Networking Laboratory
Ray Milkey4f5de002014-12-17 19:26:11 -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;
17
Jian Li80cfe452016-01-14 16:04:58 -080018import com.eclipsesource.json.Json;
Jonathan Hartf44e42c2015-08-04 09:58:46 -070019import com.eclipsesource.json.JsonArray;
20import com.eclipsesource.json.JsonObject;
21import com.google.common.collect.ImmutableSet;
Ray Milkey4f5de002014-12-17 19:26:11 -080022import org.hamcrest.Description;
Ray Milkeyeb5c7172015-06-23 14:59:27 -070023import org.hamcrest.Matchers;
Ray Milkey4f5de002014-12-17 19:26:11 -080024import org.hamcrest.TypeSafeMatcher;
25import org.junit.After;
26import org.junit.Before;
27import org.junit.Test;
28import org.onlab.osgi.ServiceDirectory;
29import org.onlab.osgi.TestServiceDirectory;
30import org.onlab.packet.MacAddress;
31import org.onlab.rest.BaseResource;
32import org.onosproject.codec.CodecService;
33import org.onosproject.codec.impl.CodecManager;
Ray Milkeyeb5c7172015-06-23 14:59:27 -070034import org.onosproject.codec.impl.FlowRuleCodec;
Ray Milkeyd43fe452015-05-29 09:35:12 -070035import org.onosproject.core.CoreService;
Ray Milkey4f5de002014-12-17 19:26:11 -080036import org.onosproject.core.DefaultGroupId;
37import org.onosproject.core.GroupId;
38import org.onosproject.net.DefaultDevice;
39import org.onosproject.net.Device;
40import org.onosproject.net.DeviceId;
Ray Milkeyeb5c7172015-06-23 14:59:27 -070041import org.onosproject.net.IndexedLambda;
Ray Milkeyd43fe452015-05-29 09:35:12 -070042import org.onosproject.net.NetTestTools;
Ray Milkey4f5de002014-12-17 19:26:11 -080043import org.onosproject.net.device.DeviceService;
44import org.onosproject.net.flow.DefaultTrafficSelector;
45import org.onosproject.net.flow.DefaultTrafficTreatment;
46import org.onosproject.net.flow.FlowEntry;
47import org.onosproject.net.flow.FlowId;
Jonathan Hartf44e42c2015-08-04 09:58:46 -070048import org.onosproject.net.flow.FlowRule;
jcc3d4e14a2015-04-21 11:32:05 +080049import org.onosproject.net.flow.FlowRuleExtPayLoad;
Ray Milkey4f5de002014-12-17 19:26:11 -080050import org.onosproject.net.flow.FlowRuleService;
51import org.onosproject.net.flow.TrafficSelector;
52import org.onosproject.net.flow.TrafficTreatment;
53import org.onosproject.net.flow.criteria.Criterion;
54import org.onosproject.net.flow.instructions.Instruction;
Yuta HIGUCHI32a53c52015-02-08 01:25:40 -080055import org.onosproject.net.flow.instructions.Instructions;
jcc3d4e14a2015-04-21 11:32:05 +080056
Jian Li9d616492016-03-09 10:52:49 -080057import javax.ws.rs.NotFoundException;
58import javax.ws.rs.client.Entity;
59import javax.ws.rs.client.WebTarget;
Jonathan Hartf44e42c2015-08-04 09:58:46 -070060import javax.ws.rs.core.MediaType;
Jian Li9d616492016-03-09 10:52:49 -080061import javax.ws.rs.core.Response;
Jonathan Hartf44e42c2015-08-04 09:58:46 -070062import java.io.InputStream;
63import java.net.HttpURLConnection;
64import java.util.HashMap;
65import java.util.HashSet;
66import java.util.Set;
Ray Milkey4f5de002014-12-17 19:26:11 -080067
68import static org.easymock.EasyMock.anyObject;
Ray Milkeyd43fe452015-05-29 09:35:12 -070069import static org.easymock.EasyMock.anyShort;
Ray Milkey4f5de002014-12-17 19:26:11 -080070import static org.easymock.EasyMock.createMock;
71import static org.easymock.EasyMock.expect;
Ray Milkeyd43fe452015-05-29 09:35:12 -070072import static org.easymock.EasyMock.expectLastCall;
Ray Milkey4f5de002014-12-17 19:26:11 -080073import static org.easymock.EasyMock.replay;
74import static org.easymock.EasyMock.verify;
75import static org.hamcrest.Matchers.containsString;
76import static org.hamcrest.Matchers.hasSize;
77import static org.hamcrest.Matchers.is;
78import static org.hamcrest.Matchers.not;
79import static org.hamcrest.Matchers.notNullValue;
80import static org.junit.Assert.assertThat;
81import static org.junit.Assert.fail;
Ray Milkeyeb5c7172015-06-23 14:59:27 -070082import static org.onosproject.net.NetTestTools.APP_ID;
Ray Milkey4f5de002014-12-17 19:26:11 -080083
84/**
85 * Unit tests for Flows REST APIs.
86 */
Ray Milkey9c3d3362015-01-28 10:39:56 -080087public class FlowsResourceTest extends ResourceTest {
Ray Milkey4f5de002014-12-17 19:26:11 -080088 final FlowRuleService mockFlowService = createMock(FlowRuleService.class);
Ray Milkeyd43fe452015-05-29 09:35:12 -070089 CoreService mockCoreService = createMock(CoreService.class);
90
Ray Milkey4f5de002014-12-17 19:26:11 -080091 final HashMap<DeviceId, Set<FlowEntry>> rules = new HashMap<>();
92
93 final DeviceService mockDeviceService = createMock(DeviceService.class);
94
95 final DeviceId deviceId1 = DeviceId.deviceId("1");
96 final DeviceId deviceId2 = DeviceId.deviceId("2");
97 final DeviceId deviceId3 = DeviceId.deviceId("3");
98 final Device device1 = new DefaultDevice(null, deviceId1, Device.Type.OTHER,
99 "", "", "", "", null);
100 final Device device2 = new DefaultDevice(null, deviceId2, Device.Type.OTHER,
101 "", "", "", "", null);
102
103 final MockFlowEntry flow1 = new MockFlowEntry(deviceId1, 1);
104 final MockFlowEntry flow2 = new MockFlowEntry(deviceId1, 2);
105
106 final MockFlowEntry flow3 = new MockFlowEntry(deviceId2, 3);
107 final MockFlowEntry flow4 = new MockFlowEntry(deviceId2, 4);
108
109 final MockFlowEntry flow5 = new MockFlowEntry(deviceId2, 5);
110 final MockFlowEntry flow6 = new MockFlowEntry(deviceId2, 6);
111
112 /**
113 * Mock class for a flow entry.
114 */
115 private static class MockFlowEntry implements FlowEntry {
116 final DeviceId deviceId;
117 final long baseValue;
118 TrafficTreatment treatment;
119 TrafficSelector selector;
120
121 public MockFlowEntry(DeviceId deviceId, long id) {
122 this.deviceId = deviceId;
123 this.baseValue = id * 100;
124 }
125
126 @Override
127 public FlowEntryState state() {
128 return FlowEntryState.ADDED;
129 }
130
131 @Override
132 public long life() {
133 return baseValue + 11;
134 }
135
136 @Override
137 public long packets() {
138 return baseValue + 22;
139 }
140
141 @Override
142 public long bytes() {
143 return baseValue + 33;
144 }
145
146 @Override
147 public long lastSeen() {
148 return baseValue + 44;
149 }
150
151 @Override
152 public int errType() {
153 return 0;
154 }
155
156 @Override
157 public int errCode() {
158 return 0;
159 }
160
161 @Override
162 public FlowId id() {
163 final long id = baseValue + 55;
164 return FlowId.valueOf(id);
165 }
166
167 @Override
alshabib08d98982015-04-21 16:25:50 -0700168 public GroupId groupId() {
169 return new DefaultGroupId(3);
Ray Milkey4f5de002014-12-17 19:26:11 -0800170 }
171
172 @Override
alshabib08d98982015-04-21 16:25:50 -0700173 public short appId() {
174 return 2;
Ray Milkey4f5de002014-12-17 19:26:11 -0800175 }
176
177 @Override
178 public int priority() {
179 return (int) (baseValue + 66);
180 }
181
182 @Override
183 public DeviceId deviceId() {
184 return deviceId;
185 }
186
187 @Override
188 public TrafficSelector selector() {
189 return selector;
190 }
191
192 @Override
193 public TrafficTreatment treatment() {
194 return treatment;
195 }
196
197 @Override
198 public int timeout() {
199 return (int) (baseValue + 77);
200 }
201
202 @Override
203 public boolean isPermanent() {
204 return false;
205 }
sangho11c30ac2015-01-22 14:30:55 -0800206
Yuta HIGUCHI32a53c52015-02-08 01:25:40 -0800207 @Override
alshabibdb774072015-04-20 13:13:51 -0700208 public int tableId() {
209 return 0;
210 }
jcc3d4e14a2015-04-21 11:32:05 +0800211
212 @Override
Jonathan Hartf44e42c2015-08-04 09:58:46 -0700213 public boolean exactMatch(FlowRule rule) {
214 return false;
215 }
216
217 @Override
jcc3d4e14a2015-04-21 11:32:05 +0800218 public FlowRuleExtPayLoad payLoad() {
219 return null;
220 }
Ray Milkey4f5de002014-12-17 19:26:11 -0800221 }
222
Ray Milkey4f5de002014-12-17 19:26:11 -0800223 /**
224 * Populates some flows used as testing data.
225 */
226 private void setupMockFlows() {
227 flow2.treatment = DefaultTrafficTreatment.builder()
Ray Milkeyeb5c7172015-06-23 14:59:27 -0700228 .add(Instructions.modL0Lambda(new IndexedLambda((short) 4)))
229 .add(Instructions.modL0Lambda(new IndexedLambda((short) 5)))
Ray Milkey4f5de002014-12-17 19:26:11 -0800230 .setEthDst(MacAddress.BROADCAST)
231 .build();
232 flow2.selector = DefaultTrafficSelector.builder()
233 .matchEthType((short) 3)
234 .matchIPProtocol((byte) 9)
235 .build();
236 flow4.treatment = DefaultTrafficTreatment.builder()
Ray Milkeyeb5c7172015-06-23 14:59:27 -0700237 .add(Instructions.modL0Lambda(new IndexedLambda((short) 6)))
Ray Milkey4f5de002014-12-17 19:26:11 -0800238 .build();
239 final Set<FlowEntry> flows1 = new HashSet<>();
240 flows1.add(flow1);
241 flows1.add(flow2);
242
243 final Set<FlowEntry> flows2 = new HashSet<>();
Ray Milkeyeb5c7172015-06-23 14:59:27 -0700244 flows2.add(flow3);
245 flows2.add(flow4);
Ray Milkey4f5de002014-12-17 19:26:11 -0800246
247 rules.put(deviceId1, flows1);
248 rules.put(deviceId2, flows2);
249
250 expect(mockFlowService.getFlowEntries(deviceId1))
251 .andReturn(rules.get(deviceId1)).anyTimes();
252 expect(mockFlowService.getFlowEntries(deviceId2))
253 .andReturn(rules.get(deviceId2)).anyTimes();
254 }
255
256 /**
257 * Sets up the global values for all the tests.
258 */
259 @Before
Ray Milkeyed0b1662015-02-05 09:34:29 -0800260 public void setUpTest() {
Ray Milkey4f5de002014-12-17 19:26:11 -0800261 // Mock device service
262 expect(mockDeviceService.getDevice(deviceId1))
263 .andReturn(device1);
264 expect(mockDeviceService.getDevice(deviceId2))
265 .andReturn(device2);
266 expect(mockDeviceService.getDevices())
267 .andReturn(ImmutableSet.of(device1, device2));
268
Ray Milkeyd43fe452015-05-29 09:35:12 -0700269 // Mock Core Service
270 expect(mockCoreService.getAppId(anyShort()))
271 .andReturn(NetTestTools.APP_ID).anyTimes();
Ray Milkeyeb5c7172015-06-23 14:59:27 -0700272 expect(mockCoreService.registerApplication(FlowRuleCodec.REST_APP_ID))
273 .andReturn(APP_ID).anyTimes();
Ray Milkeyd43fe452015-05-29 09:35:12 -0700274 replay(mockCoreService);
275
Ray Milkey4f5de002014-12-17 19:26:11 -0800276 // Register the services needed for the test
277 final CodecManager codecService = new CodecManager();
278 codecService.activate();
279 ServiceDirectory testDirectory =
280 new TestServiceDirectory()
281 .add(FlowRuleService.class, mockFlowService)
282 .add(DeviceService.class, mockDeviceService)
Ray Milkeyd43fe452015-05-29 09:35:12 -0700283 .add(CodecService.class, codecService)
284 .add(CoreService.class, mockCoreService);
Ray Milkey4f5de002014-12-17 19:26:11 -0800285
286 BaseResource.setServiceDirectory(testDirectory);
287 }
288
289 /**
290 * Cleans up and verifies the mocks.
Ray Milkey4f5de002014-12-17 19:26:11 -0800291 */
292 @After
Ray Milkeyed0b1662015-02-05 09:34:29 -0800293 public void tearDownTest() {
Ray Milkey4f5de002014-12-17 19:26:11 -0800294 verify(mockFlowService);
Ray Milkeyd43fe452015-05-29 09:35:12 -0700295 verify(mockCoreService);
Ray Milkey4f5de002014-12-17 19:26:11 -0800296 }
297
298 /**
299 * Hamcrest matcher to check that a flow representation in JSON matches
300 * the actual flow entry.
301 */
302 public static class FlowJsonMatcher extends TypeSafeMatcher<JsonObject> {
303 private final FlowEntry flow;
Ray Milkeybe539db2015-09-04 11:00:43 -0700304 private final String expectedAppId;
Ray Milkey4f5de002014-12-17 19:26:11 -0800305 private String reason = "";
306
Ray Milkeybe539db2015-09-04 11:00:43 -0700307 public FlowJsonMatcher(FlowEntry flowValue, String expectedAppIdValue) {
Ray Milkey4f5de002014-12-17 19:26:11 -0800308 flow = flowValue;
Ray Milkeybe539db2015-09-04 11:00:43 -0700309 expectedAppId = expectedAppIdValue;
Ray Milkey4f5de002014-12-17 19:26:11 -0800310 }
311
312 @Override
313 public boolean matchesSafely(JsonObject jsonFlow) {
314 // check id
315 final String jsonId = jsonFlow.get("id").asString();
316 final String flowId = Long.toString(flow.id().value());
317 if (!jsonId.equals(flowId)) {
318 reason = "id " + flow.id().toString();
319 return false;
320 }
321
322 // check application id
Ray Milkeybe539db2015-09-04 11:00:43 -0700323 final String jsonAppId = jsonFlow.get("appId").asString();
324 if (!jsonAppId.equals(expectedAppId)) {
Ray Milkey4f5de002014-12-17 19:26:11 -0800325 reason = "appId " + Short.toString(flow.appId());
326 return false;
327 }
328
329 // check device id
330 final String jsonDeviceId = jsonFlow.get("deviceId").asString();
331 if (!jsonDeviceId.equals(flow.deviceId().toString())) {
332 reason = "deviceId " + flow.deviceId();
333 return false;
334 }
335
336 // check treatment and instructions array
337 if (flow.treatment() != null) {
338 final JsonObject jsonTreatment = jsonFlow.get("treatment").asObject();
339 final JsonArray jsonInstructions = jsonTreatment.get("instructions").asArray();
Ray Milkey42507352015-03-20 15:16:10 -0700340 if (flow.treatment().immediate().size() != jsonInstructions.size()) {
Ray Milkey4f5de002014-12-17 19:26:11 -0800341 reason = "instructions array size of " +
Ray Milkey42507352015-03-20 15:16:10 -0700342 Integer.toString(flow.treatment().immediate().size());
Ray Milkey4f5de002014-12-17 19:26:11 -0800343 return false;
344 }
Ray Milkey42507352015-03-20 15:16:10 -0700345 for (final Instruction instruction : flow.treatment().immediate()) {
Ray Milkey4f5de002014-12-17 19:26:11 -0800346 boolean instructionFound = false;
Ray Milkey4f5de002014-12-17 19:26:11 -0800347 for (int instructionIndex = 0; instructionIndex < jsonInstructions.size(); instructionIndex++) {
Ray Milkeyc95bb9d2015-01-06 10:28:24 -0800348 final String jsonType =
349 jsonInstructions.get(instructionIndex)
350 .asObject().get("type").asString();
351 final String instructionType = instruction.type().name();
352 if (jsonType.equals(instructionType)) {
Ray Milkey4f5de002014-12-17 19:26:11 -0800353 instructionFound = true;
354 }
355 }
356 if (!instructionFound) {
Ray Milkeyc95bb9d2015-01-06 10:28:24 -0800357 reason = "instruction " + instruction.toString();
Ray Milkey4f5de002014-12-17 19:26:11 -0800358 return false;
359 }
360 }
361 }
362
363 // check selector and criteria array
364 if (flow.selector() != null) {
365 final JsonObject jsonTreatment = jsonFlow.get("selector").asObject();
366 final JsonArray jsonCriteria = jsonTreatment.get("criteria").asArray();
367 if (flow.selector().criteria().size() != jsonCriteria.size()) {
368 reason = "criteria array size of " +
369 Integer.toString(flow.selector().criteria().size());
370 return false;
371 }
372 for (final Criterion criterion : flow.selector().criteria()) {
373 boolean criterionFound = false;
Ray Milkeyc95bb9d2015-01-06 10:28:24 -0800374
Ray Milkey4f5de002014-12-17 19:26:11 -0800375 for (int criterionIndex = 0; criterionIndex < jsonCriteria.size(); criterionIndex++) {
Ray Milkeyc95bb9d2015-01-06 10:28:24 -0800376 final String jsonType =
377 jsonCriteria.get(criterionIndex)
378 .asObject().get("type").asString();
379 final String criterionType = criterion.type().name();
380 if (jsonType.equals(criterionType)) {
Ray Milkey4f5de002014-12-17 19:26:11 -0800381 criterionFound = true;
382 }
383 }
384 if (!criterionFound) {
Ray Milkeyc95bb9d2015-01-06 10:28:24 -0800385 reason = "criterion " + criterion.toString();
Ray Milkey4f5de002014-12-17 19:26:11 -0800386 return false;
387 }
388 }
389 }
390
391 return true;
392 }
393
394 @Override
395 public void describeTo(Description description) {
396 description.appendText(reason);
397 }
398 }
399
400 /**
401 * Factory to allocate a flow matcher.
402 *
403 * @param flow flow object we are looking for
404 * @return matcher
405 */
Ray Milkeybe539db2015-09-04 11:00:43 -0700406 private static FlowJsonMatcher matchesFlow(FlowEntry flow, String expectedAppName) {
407 return new FlowJsonMatcher(flow, expectedAppName);
Ray Milkey4f5de002014-12-17 19:26:11 -0800408 }
409
410 /**
411 * Hamcrest matcher to check that a flow is represented properly in a JSON
412 * array of flows.
413 */
414 public static class FlowJsonArrayMatcher extends TypeSafeMatcher<JsonArray> {
415 private final FlowEntry flow;
416 private String reason = "";
417
418 public FlowJsonArrayMatcher(FlowEntry flowValue) {
419 flow = flowValue;
420 }
421
422 @Override
423 public boolean matchesSafely(JsonArray json) {
424 boolean flowFound = false;
425
426 for (int jsonFlowIndex = 0; jsonFlowIndex < json.size();
427 jsonFlowIndex++) {
428
429 final JsonObject jsonFlow = json.get(jsonFlowIndex).asObject();
430
431 final String flowId = Long.toString(flow.id().value());
432 final String jsonFlowId = jsonFlow.get("id").asString();
433 if (jsonFlowId.equals(flowId)) {
434 flowFound = true;
435
436 // We found the correct flow, check attribute values
Ray Milkeybe539db2015-09-04 11:00:43 -0700437 assertThat(jsonFlow, matchesFlow(flow, APP_ID.name()));
Ray Milkey4f5de002014-12-17 19:26:11 -0800438 }
439 }
440 if (!flowFound) {
441 reason = "Flow with id " + flow.id().toString() + " not found";
442 return false;
443 } else {
444 return true;
445 }
446 }
447
448 @Override
449 public void describeTo(Description description) {
450 description.appendText(reason);
451 }
452 }
453
454 /**
455 * Factory to allocate a flow array matcher.
456 *
457 * @param flow flow object we are looking for
458 * @return matcher
459 */
460 private static FlowJsonArrayMatcher hasFlow(FlowEntry flow) {
461 return new FlowJsonArrayMatcher(flow);
462 }
463
464 /**
465 * Tests the result of the rest api GET when there are no flows.
466 */
467 @Test
468 public void testFlowsEmptyArray() {
469 expect(mockFlowService.getFlowEntries(deviceId1))
470 .andReturn(null).anyTimes();
471 expect(mockFlowService.getFlowEntries(deviceId2))
472 .andReturn(null).anyTimes();
473 replay(mockFlowService);
474 replay(mockDeviceService);
Jian Li9d616492016-03-09 10:52:49 -0800475 final WebTarget wt = target();
476 final String response = wt.path("flows").request().get(String.class);
Ray Milkey4f5de002014-12-17 19:26:11 -0800477 assertThat(response, is("{\"flows\":[]}"));
478 }
479
480 /**
481 * Tests the result of the rest api GET when there are active flows.
482 */
483 @Test
484 public void testFlowsPopulatedArray() {
485 setupMockFlows();
486 replay(mockFlowService);
487 replay(mockDeviceService);
Jian Li9d616492016-03-09 10:52:49 -0800488 final WebTarget wt = target();
489 final String response = wt.path("flows").request().get(String.class);
Jian Li80cfe452016-01-14 16:04:58 -0800490 final JsonObject result = Json.parse(response).asObject();
Ray Milkey4f5de002014-12-17 19:26:11 -0800491 assertThat(result, notNullValue());
492
493 assertThat(result.names(), hasSize(1));
494 assertThat(result.names().get(0), is("flows"));
495 final JsonArray jsonFlows = result.get("flows").asArray();
496 assertThat(jsonFlows, notNullValue());
497 assertThat(jsonFlows, hasFlow(flow1));
498 assertThat(jsonFlows, hasFlow(flow2));
499 assertThat(jsonFlows, hasFlow(flow3));
500 assertThat(jsonFlows, hasFlow(flow4));
501 }
502
503 /**
504 * Tests the result of a rest api GET for a device.
505 */
506 @Test
507 public void testFlowsSingleDevice() {
508 setupMockFlows();
509 final Set<FlowEntry> flows = new HashSet<>();
510 flows.add(flow5);
511 flows.add(flow6);
512 expect(mockFlowService.getFlowEntries(anyObject()))
513 .andReturn(flows).anyTimes();
514 replay(mockFlowService);
515 replay(mockDeviceService);
Jian Li9d616492016-03-09 10:52:49 -0800516 final WebTarget wt = target();
517 final String response = wt.path("flows/" + deviceId3).request().get(String.class);
Jian Li80cfe452016-01-14 16:04:58 -0800518 final JsonObject result = Json.parse(response).asObject();
Ray Milkey4f5de002014-12-17 19:26:11 -0800519 assertThat(result, notNullValue());
520
521 assertThat(result.names(), hasSize(1));
522 assertThat(result.names().get(0), is("flows"));
523 final JsonArray jsonFlows = result.get("flows").asArray();
524 assertThat(jsonFlows, notNullValue());
525 assertThat(jsonFlows, hasFlow(flow5));
526 assertThat(jsonFlows, hasFlow(flow6));
527 }
528
529 /**
530 * Tests the result of a rest api GET for a device.
531 */
532 @Test
533 public void testFlowsSingleDeviceWithFlowId() {
534 setupMockFlows();
535 final Set<FlowEntry> flows = new HashSet<>();
536 flows.add(flow5);
537 flows.add(flow6);
538 expect(mockFlowService.getFlowEntries(anyObject()))
539 .andReturn(flows).anyTimes();
540 replay(mockFlowService);
541 replay(mockDeviceService);
Jian Li9d616492016-03-09 10:52:49 -0800542 final WebTarget wt = target();
543 final String response = wt.path("flows/" + deviceId3 + "/"
544 + Long.toString(flow5.id().value())).request().get(String.class);
Jian Li80cfe452016-01-14 16:04:58 -0800545 final JsonObject result = Json.parse(response).asObject();
Ray Milkey4f5de002014-12-17 19:26:11 -0800546 assertThat(result, notNullValue());
547
548 assertThat(result.names(), hasSize(1));
549 assertThat(result.names().get(0), is("flows"));
550 final JsonArray jsonFlows = result.get("flows").asArray();
551 assertThat(jsonFlows, notNullValue());
552 assertThat(jsonFlows, hasFlow(flow5));
553 assertThat(jsonFlows, not(hasFlow(flow6)));
554 }
555
556 /**
557 * Tests that a fetch of a non-existent device object throws an exception.
558 */
559 @Test
560 public void testBadGet() {
Jian Li9d616492016-03-09 10:52:49 -0800561 expect(mockFlowService.getFlowEntries(anyObject()))
Ray Milkey4f5de002014-12-17 19:26:11 -0800562 .andReturn(null).anyTimes();
563 replay(mockFlowService);
564 replay(mockDeviceService);
565
Jian Li9d616492016-03-09 10:52:49 -0800566 WebTarget wt = target();
Ray Milkey4f5de002014-12-17 19:26:11 -0800567 try {
Jian Li9d616492016-03-09 10:52:49 -0800568 wt.path("flows/0").request().get(String.class);
Ray Milkey4f5de002014-12-17 19:26:11 -0800569 fail("Fetch of non-existent device did not throw an exception");
Jian Li9d616492016-03-09 10:52:49 -0800570 } catch (NotFoundException ex) {
Ray Milkey4f5de002014-12-17 19:26:11 -0800571 assertThat(ex.getMessage(),
Jian Li9d616492016-03-09 10:52:49 -0800572 containsString("HTTP 404 Not Found"));
Ray Milkey4f5de002014-12-17 19:26:11 -0800573 }
574 }
Ray Milkeyd43fe452015-05-29 09:35:12 -0700575
576 /**
577 * Tests creating a flow with POST.
578 */
579 @Test
580 public void testPost() {
Ray Milkeyd43fe452015-05-29 09:35:12 -0700581 mockFlowService.applyFlowRules(anyObject());
582 expectLastCall();
583 replay(mockFlowService);
584
Jian Li9d616492016-03-09 10:52:49 -0800585 WebTarget wt = target();
Phaneendra Manda2be2f882015-11-11 15:23:40 +0530586 InputStream jsonStream = FlowsResourceTest.class
Ray Milkeyb82c42b2015-06-30 09:42:20 -0700587 .getResourceAsStream("post-flow.json");
Ray Milkeyd43fe452015-05-29 09:35:12 -0700588
Jian Li9d616492016-03-09 10:52:49 -0800589 Response response = wt.path("flows/of:0000000000000001")
590 .request(MediaType.APPLICATION_JSON_TYPE)
591 .post(Entity.json(jsonStream));
Ray Milkeyeb5c7172015-06-23 14:59:27 -0700592 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
593 String location = response.getLocation().getPath();
594 assertThat(location, Matchers.startsWith("/flows/of:0000000000000001/"));
595 }
596
597 /**
598 * Tests deleting a flow.
599 */
600 @Test
601 public void testDelete() {
602 setupMockFlows();
603 mockFlowService.removeFlowRules(anyObject());
604 expectLastCall();
605 replay(mockFlowService);
606
Jian Li9d616492016-03-09 10:52:49 -0800607 WebTarget wt = target();
Ray Milkeyeb5c7172015-06-23 14:59:27 -0700608
609 String location = "/flows/1/155";
610
Jian Li9d616492016-03-09 10:52:49 -0800611 Response deleteResponse = wt.path(location)
612 .request(MediaType.APPLICATION_JSON_TYPE)
613 .delete();
Ray Milkeyeb5c7172015-06-23 14:59:27 -0700614 assertThat(deleteResponse.getStatus(),
615 is(HttpURLConnection.HTTP_NO_CONTENT));
Ray Milkeyd43fe452015-05-29 09:35:12 -0700616 }
Ray Milkey4f5de002014-12-17 19:26:11 -0800617}