blob: 8d5c55f244417d68ae4918ef56254b7a542ac614 [file] [log] [blame]
Ray Milkey2b217142014-12-15 09:24:24 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
Ray Milkey2b217142014-12-15 09:24:24 -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 */
Jian Li8ae91202016-03-24 14:36:16 -070016package org.onosproject.rest.resources;
Ray Milkey2b217142014-12-15 09:24:24 -080017
Author Namee252a002016-09-26 22:42:24 +053018import com.eclipsesource.json.Json;
19import com.eclipsesource.json.JsonArray;
20import com.eclipsesource.json.JsonObject;
21import com.eclipsesource.json.JsonValue;
Ray Milkey2b217142014-12-15 09:24:24 -080022import org.hamcrest.Description;
Ray Milkeyb82c42b2015-06-30 09:42:20 -070023import org.hamcrest.Matchers;
Ray Milkey2b217142014-12-15 09:24:24 -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;
Author Namee252a002016-09-26 22:42:24 +053030import org.onlab.packet.MacAddress;
Ray Milkey2b217142014-12-15 09:24:24 -080031import org.onlab.rest.BaseResource;
32import org.onosproject.codec.CodecService;
33import org.onosproject.codec.impl.CodecManager;
34import org.onosproject.core.ApplicationId;
Ayaka Koshibec06c89b2015-02-10 19:25:41 -080035import org.onosproject.core.CoreService;
Ray Milkey2b217142014-12-15 09:24:24 -080036import org.onosproject.core.DefaultApplicationId;
Author Namee252a002016-09-26 22:42:24 +053037import org.onosproject.core.GroupId;
Ray Milkey2b217142014-12-15 09:24:24 -080038import org.onosproject.core.IdGenerator;
Author Namee252a002016-09-26 22:42:24 +053039import org.onosproject.net.DeviceId;
Ray Milkey2b217142014-12-15 09:24:24 -080040import org.onosproject.net.NetworkResource;
Author Namee252a002016-09-26 22:42:24 +053041import org.onosproject.net.flow.DefaultTrafficSelector;
42import org.onosproject.net.flow.DefaultTrafficTreatment;
43import org.onosproject.net.flow.FlowEntry;
Ray Milkey634eb172017-04-05 14:48:50 -070044import org.onosproject.net.flow.FlowEntryAdapter;
Author Namee252a002016-09-26 22:42:24 +053045import org.onosproject.net.flow.FlowId;
46import org.onosproject.net.flow.FlowRule;
47import org.onosproject.net.flow.FlowRuleExtPayLoad;
48import org.onosproject.net.flow.FlowRuleService;
49import org.onosproject.net.flow.TrafficSelector;
50import org.onosproject.net.flow.TrafficTreatment;
51import org.onosproject.net.flow.criteria.Criterion;
52import org.onosproject.net.flow.instructions.Instruction;
Ray Milkey7b158512015-07-21 16:32:43 -070053import org.onosproject.net.intent.FakeIntentManager;
Author Namee252a002016-09-26 22:42:24 +053054import org.onosproject.net.intent.FlowRuleIntent;
Ray Milkey2b217142014-12-15 09:24:24 -080055import org.onosproject.net.intent.Intent;
Ray Milkey2b217142014-12-15 09:24:24 -080056import org.onosproject.net.intent.IntentService;
Ray Milkey1534f8d2015-05-13 15:42:50 -070057import org.onosproject.net.intent.IntentState;
Ray Milkeyf9af43c2015-02-09 16:45:48 -080058import org.onosproject.net.intent.Key;
Ray Milkey2b217142014-12-15 09:24:24 -080059
Author Namee252a002016-09-26 22:42:24 +053060import javax.ws.rs.NotFoundException;
61import javax.ws.rs.client.Entity;
62import javax.ws.rs.client.WebTarget;
63import javax.ws.rs.core.MediaType;
64import javax.ws.rs.core.Response;
65import java.io.InputStream;
66import java.net.HttpURLConnection;
67import java.util.ArrayList;
68import java.util.Collections;
69import java.util.HashSet;
70import java.util.List;
71import java.util.concurrent.TimeUnit;
Ray Milkey2b217142014-12-15 09:24:24 -080072
Author Namee252a002016-09-26 22:42:24 +053073import static java.util.concurrent.TimeUnit.SECONDS;
74import static org.easymock.EasyMock.*;
75import static org.hamcrest.Matchers.*;
Ray Milkey2b217142014-12-15 09:24:24 -080076import static org.junit.Assert.assertThat;
77import static org.junit.Assert.fail;
Ray Milkey43a28222015-02-23 13:57:58 -080078import static org.onosproject.net.intent.IntentTestsMocks.MockIntent;
Ray Milkey7c251822016-04-06 17:38:25 -070079import static org.onosproject.net.intent.MockIdGenerator.bindNewGenerator;
Ray Milkey2b217142014-12-15 09:24:24 -080080
81/**
82 * Unit tests for Intents REST APIs.
83 */
Ray Milkey9c3d3362015-01-28 10:39:56 -080084public class IntentsResourceTest extends ResourceTest {
Author Namee252a002016-09-26 22:42:24 +053085
86
87 private static final String APPID = "appId";
88 private static final String CRITERIA = "criteria";
89 private static final String DEVICE_ID = "deviceId";
90 private static final String ID = "id";
91 private static final String INSTRUCTIONS = "instructions";
92 private static final String PATHS = "paths";
93 private static final String SELECTOR = "selector";
94 private static final String SPACE = " ";
95 private static final String TREATMENT = "treatment";
96 private static final String TYPE = "type";
97
Ray Milkey2b217142014-12-15 09:24:24 -080098 final IntentService mockIntentService = createMock(IntentService.class);
Ayaka Koshibec06c89b2015-02-10 19:25:41 -080099 final CoreService mockCoreService = createMock(CoreService.class);
Author Namee252a002016-09-26 22:42:24 +0530100 final FlowRuleService mockFlowService = createMock(FlowRuleService.class);
Ray Milkey2b217142014-12-15 09:24:24 -0800101 final HashSet<Intent> intents = new HashSet<>();
Author Namee252a002016-09-26 22:42:24 +0530102 final List<org.onosproject.net.intent.Intent> installableIntents = new ArrayList<>();
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800103 private static final ApplicationId APP_ID = new DefaultApplicationId(1, "test");
Ray Milkey2b217142014-12-15 09:24:24 -0800104 private IdGenerator mockGenerator;
105
Author Namee252a002016-09-26 22:42:24 +0530106 final DeviceId deviceId1 = DeviceId.deviceId("1");
107
108 final TrafficTreatment treatment1 = DefaultTrafficTreatment.builder()
109 .setEthDst(MacAddress.BROADCAST)
110 .build();
111 final TrafficTreatment treatment2 = DefaultTrafficTreatment.builder()
112 .setEthDst(MacAddress.IPV4_MULTICAST)
113 .build();
114
115 final TrafficSelector selector1 = DefaultTrafficSelector.builder()
116 .matchEthType((short) 3)
117 .matchIPProtocol((byte) 9)
118 .build();
119 final TrafficSelector selector2 = DefaultTrafficSelector.builder()
120 .matchEthType((short) 4)
121 .matchIPProtocol((byte) 10)
122 .build();
123
124 final MockFlowEntry flow1 = new MockFlowEntry(deviceId1, 1, treatment1, selector1);
125 final MockFlowEntry flow2 = new MockFlowEntry(deviceId1, 2, treatment2, selector2);
126
127 final MockFlowRule flowRule1 = new MockFlowRule(deviceId1, 1, treatment1, selector1);
128 final MockFlowRule flowRule2 = new MockFlowRule(deviceId1, 2, treatment2, selector2);
129
Ray Milkey2b217142014-12-15 09:24:24 -0800130 private class MockResource implements NetworkResource {
131 int id;
132
133 MockResource(int id) {
134 this.id = id;
135 }
136
Ayaka Koshibec06c89b2015-02-10 19:25:41 -0800137 @Override
Ray Milkey2b217142014-12-15 09:24:24 -0800138 public String toString() {
139 return "Resource " + Integer.toString(id);
140 }
141 }
142
Ray Milkey2b217142014-12-15 09:24:24 -0800143 /**
Author Namee252a002016-09-26 22:42:24 +0530144 * Mock class for a flow entry.
145 */
Ray Milkey634eb172017-04-05 14:48:50 -0700146 private static class MockFlowEntry extends FlowEntryAdapter {
Author Namee252a002016-09-26 22:42:24 +0530147 final DeviceId deviceId;
148 final long baseValue;
149 TrafficTreatment treatment;
150 TrafficSelector selector;
151
152 public MockFlowEntry(DeviceId deviceId, long id,
153 TrafficTreatment treatment,
154 TrafficSelector selector) {
155 this.deviceId = deviceId;
156 this.baseValue = id * 100;
157 this.treatment = treatment;
158 this.selector = selector;
159 }
160
161 @Override
Author Namee252a002016-09-26 22:42:24 +0530162 public long life() {
163 return life(SECONDS);
164 }
165
166 @Override
167 public long life(TimeUnit timeUnit) {
168 return SECONDS.convert(baseValue + 11, timeUnit);
169 }
170
171 @Override
172 public long packets() {
173 return baseValue + 22;
174 }
175
176 @Override
177 public long bytes() {
178 return baseValue + 33;
179 }
180
181 @Override
182 public long lastSeen() {
183 return baseValue + 44;
184 }
185
186 @Override
Author Namee252a002016-09-26 22:42:24 +0530187 public FlowId id() {
188 final long id = baseValue + 55;
189 return FlowId.valueOf(id);
190 }
191
192 @Override
193 public GroupId groupId() {
Yi Tsengfa394de2017-02-01 11:26:40 -0800194 return new GroupId(3);
Author Namee252a002016-09-26 22:42:24 +0530195 }
196
197 @Override
198 public short appId() {
199 return 1;
200 }
201
202 @Override
203 public int priority() {
204 return (int) (baseValue + 66);
205 }
206
207 @Override
208 public DeviceId deviceId() {
209 return deviceId;
210 }
211
212 @Override
213 public TrafficSelector selector() {
214 return selector;
215 }
216
217 @Override
218 public TrafficTreatment treatment() {
219 return treatment;
220 }
221
222 @Override
223 public int timeout() {
224 return (int) (baseValue + 77);
225 }
226
Author Namee252a002016-09-26 22:42:24 +0530227
228 @Override
229 public boolean exactMatch(FlowRule rule) {
230 return this.appId() == rule.appId() &&
231 this.deviceId().equals(rule.deviceId()) &&
232 this.id().equals(rule.id()) &&
233 this.treatment.equals(rule.treatment()) &&
234 this.selector().equals(rule.selector());
235 }
236
237 @Override
Author Namee252a002016-09-26 22:42:24 +0530238 public String toString() {
239 return id().id().toString();
240 }
241 }
242
243 /**
244 * Mock class for a flow rule.
245 */
246 private static class MockFlowRule implements FlowRule {
247
248 final DeviceId deviceId;
249 final long baseValue;
250 TrafficTreatment treatment;
251 TrafficSelector selector;
252
253 public MockFlowRule(DeviceId deviceId,
254 long id,
255 TrafficTreatment treatment,
256 TrafficSelector selector) {
257 this.deviceId = deviceId;
258 this.baseValue = id * 100;
259 this.treatment = treatment;
260 this.selector = selector;
261 }
262
263 @Override
264 public FlowId id() {
265 long id = baseValue + 55;
266 return FlowId.valueOf(id);
267 }
268
269 @Override
270 public short appId() {
271 return 1;
272 }
273
274 @Override
275 public GroupId groupId() {
Yi Tsengfa394de2017-02-01 11:26:40 -0800276 return new GroupId(3);
Author Namee252a002016-09-26 22:42:24 +0530277 }
278
279 @Override
280 public int priority() {
281 return 0;
282 }
283
284 @Override
285 public DeviceId deviceId() {
286 return deviceId;
287 }
288
289 @Override
290 public TrafficSelector selector() {
291 return selector;
292 }
293
294 @Override
295 public TrafficTreatment treatment() {
296 return treatment;
297 }
298
299 @Override
300 public int timeout() {
301 return (int) (baseValue + 77);
302 }
303
304 @Override
305 public int hardTimeout() {
306 return 0;
307 }
308
309 @Override
310 public FlowRemoveReason reason() {
311 return FlowRemoveReason.NO_REASON;
312 }
313
314 @Override
315 public boolean isPermanent() {
316 return false;
317 }
318
319 @Override
320 public int tableId() {
321 return 0;
322 }
323
324 @Override
325 public boolean exactMatch(FlowRule rule) {
326 return false;
327 }
328
329 @Override
330 public FlowRuleExtPayLoad payLoad() {
331 return null;
332 }
333 }
334
335 /**
Ray Milkey2b217142014-12-15 09:24:24 -0800336 * Hamcrest matcher to check that an intent representation in JSON matches
337 * the actual intent.
338 */
339 public static class IntentJsonMatcher extends TypeSafeMatcher<JsonObject> {
340 private final Intent intent;
341 private String reason = "";
342
343 public IntentJsonMatcher(Intent intentValue) {
344 intent = intentValue;
345 }
346
347 @Override
348 public boolean matchesSafely(JsonObject jsonIntent) {
349 // check id
350 final String jsonId = jsonIntent.get("id").asString();
351 if (!jsonId.equals(intent.id().toString())) {
352 reason = "id " + intent.id().toString();
353 return false;
354 }
355
356 // check application id
Ray Milkeyf7cb4012015-07-20 13:01:07 -0700357
Ray Milkey2b217142014-12-15 09:24:24 -0800358 final String jsonAppId = jsonIntent.get("appId").asString();
Ray Milkeyf7cb4012015-07-20 13:01:07 -0700359 final String appId = intent.appId().name();
360 if (!jsonAppId.equals(appId)) {
361 reason = "appId was " + jsonAppId;
Ray Milkey2b217142014-12-15 09:24:24 -0800362 return false;
363 }
364
365 // check intent type
366 final String jsonType = jsonIntent.get("type").asString();
367 if (!jsonType.equals("MockIntent")) {
368 reason = "type MockIntent";
369 return false;
370 }
371
Ray Milkey1534f8d2015-05-13 15:42:50 -0700372 // check state field
373 final String jsonState = jsonIntent.get("state").asString();
374 if (!jsonState.equals("INSTALLED")) {
375 reason = "state INSTALLED";
376 return false;
377 }
378
Ray Milkey2b217142014-12-15 09:24:24 -0800379 // check resources array
380 final JsonArray jsonResources = jsonIntent.get("resources").asArray();
381 if (intent.resources() != null) {
382 if (intent.resources().size() != jsonResources.size()) {
383 reason = "resources array size of " + Integer.toString(intent.resources().size());
384 return false;
385 }
386 for (final NetworkResource resource : intent.resources()) {
387 boolean resourceFound = false;
388 final String resourceString = resource.toString();
389 for (int resourceIndex = 0; resourceIndex < jsonResources.size(); resourceIndex++) {
390 final JsonValue value = jsonResources.get(resourceIndex);
391 if (value.asString().equals(resourceString)) {
392 resourceFound = true;
393 }
394 }
395 if (!resourceFound) {
396 reason = "resource " + resourceString;
397 return false;
398 }
399 }
400 } else if (jsonResources.size() != 0) {
401 reason = "resources array empty";
402 return false;
403 }
404 return true;
405 }
406
407 @Override
408 public void describeTo(Description description) {
409 description.appendText(reason);
410 }
411 }
412
413 /**
414 * Factory to allocate an intent matcher.
415 *
416 * @param intent intent object we are looking for
417 * @return matcher
418 */
419 private static IntentJsonMatcher matchesIntent(Intent intent) {
420 return new IntentJsonMatcher(intent);
421 }
422
423 /**
Author Namee252a002016-09-26 22:42:24 +0530424 * Factory to allocate an IntentRelatedFlows matcher.
425 *
426 * @param pathEntries list of path conatining flow entries of a particular intent
427 * @param expectedAppId expected app id we are looking for
428 * @return matcher
429 */
430 private static IntentStatsJsonMatcher matchesRelatedFlowEntries(
431 List<List<FlowEntry>> pathEntries,
432 final String expectedAppId) {
433 return new IntentStatsJsonMatcher(pathEntries, expectedAppId);
434 }
435
436 /**
437 * Hamcrest matcher to check that an list of flowEntries in JSON matches
438 * the actual list of flow entries.
439 */
440 public static class IntentStatsJsonMatcher extends
441 TypeSafeMatcher<JsonObject> {
442
443 private final List<List<FlowEntry>> pathEntries;
444 private final String expectedAppId;
445 private String reason = "";
446
447 public IntentStatsJsonMatcher(
448 final List<List<FlowEntry>> pathEntries,
449 final String expectedAppId) {
450 this.pathEntries = pathEntries;
451 this.expectedAppId = expectedAppId;
452 }
453
454 @Override
455 public boolean matchesSafely(JsonObject jsonIntent) {
456 int jsonPathIndex = 0;
457 JsonArray jsonPaths = jsonIntent.get(PATHS).asArray();
458
459 if (pathEntries != null) {
460
rohitsharanfd747602017-01-23 21:57:28 +0530461 if (pathEntries.size() == 0) {
462 reason = "pathEntries array empty";
463 return false;
464 }
465
Author Namee252a002016-09-26 22:42:24 +0530466 if (pathEntries.size() != jsonPaths.size()) {
467 reason = "path entries array size of " +
468 Integer.toString(pathEntries.size());
469 return false;
470 }
471
472 for (List<FlowEntry> flowEntries : pathEntries) {
473 JsonArray jsonFlowEntries = jsonPaths.get(
474 jsonPathIndex++).asArray();
475
476 if (flowEntries.size() != jsonFlowEntries.size()) {
477 reason = "flow entries array size of " +
478 Integer.toString(pathEntries.size());
479
480 return false;
481 }
482
483 int jsonFlowEntryIndex = 0;
484 for (FlowEntry flow : flowEntries) {
485
486 JsonObject jsonFlow = jsonFlowEntries.get(
487 jsonFlowEntryIndex++).asObject();
488
489 String jsonId = jsonFlow.get(ID).asString();
490 String flowId = Long.toString(flow.id().value());
491 if (!jsonId.equals(flowId)) {
492 reason = ID + SPACE + flow.id();
493 return false;
494 }
495
496 // check application id
497 String jsonAppId = jsonFlow.get(APPID).asString();
498 if (!jsonAppId.equals(expectedAppId)) {
499 reason = APPID + SPACE + Short.toString(flow.appId());
500 return false;
501 }
502
503 // check device id
504 String jsonDeviceId =
505 jsonFlow.get(DEVICE_ID).asString();
506
507 if (!jsonDeviceId.equals(flow.deviceId().toString())) {
508 reason = DEVICE_ID + SPACE + flow.deviceId();
509 return false;
510 }
511
512 if (!checkFlowTreatment(flow, jsonFlow)) {
513 return false;
514 }
515
516 if (!checkFlowSelector(flow, jsonFlow)) {
517 return false;
518 }
519
520 }
521
522 }
rohitsharanfd747602017-01-23 21:57:28 +0530523 } else {
Author Namee252a002016-09-26 22:42:24 +0530524 reason = "pathEntries array empty";
525 return false;
526 }
527
528 return true;
529 }
530
531 // check treatment and instructions array.
532 private boolean checkFlowTreatment(FlowEntry flow, JsonObject jsonFlow) {
533
534 if (flow.treatment() != null) {
535 JsonObject jsonTreatment =
536 jsonFlow.get(TREATMENT).asObject();
537 JsonArray jsonInstructions =
538 jsonTreatment.get(INSTRUCTIONS).asArray();
539
540 if (flow.treatment().immediate().size() !=
541 jsonInstructions.size()) {
542 reason = "instructions array size of " +
543 flow.treatment().immediate().size();
544
545 return false;
546 }
547 for (Instruction instruction :
548 flow.treatment().immediate()) {
549 boolean instructionFound = false;
550 for (int instructionIndex = 0;
551 instructionIndex < jsonInstructions.size();
552 instructionIndex++) {
553 String jsonType =
554 jsonInstructions.get(instructionIndex)
555 .asObject().get(TYPE).asString();
556
557 String instructionType =
558 instruction.type().name();
559
560 if (jsonType.equals(instructionType)) {
561 instructionFound = true;
562 }
563 }
564 if (!instructionFound) {
565 reason = INSTRUCTIONS + SPACE + instruction;
566 return false;
567 }
568 }
569 }
570 return true;
571 }
572
573 // check selector and criteria array.
574 private boolean checkFlowSelector(FlowEntry flow, JsonObject jsonFlow) {
575
576 if (flow.selector() != null) {
577 JsonObject jsonTreatment =
578 jsonFlow.get(SELECTOR).asObject();
579
580 JsonArray jsonCriteria =
581 jsonTreatment.get(CRITERIA).asArray();
582
583 if (flow.selector().criteria().size() != jsonCriteria.size()) {
584 reason = CRITERIA + " array size of " +
585 Integer.toString(flow.selector().criteria().size());
586 return false;
587 }
588 for (Criterion criterion : flow.selector().criteria()) {
589 boolean criterionFound = false;
590
591 for (int criterionIndex = 0;
592 criterionIndex < jsonCriteria.size();
593 criterionIndex++) {
594 String jsonType =
595 jsonCriteria.get(criterionIndex)
596 .asObject().get(TYPE).asString();
597 String criterionType = criterion.type().name();
598 if (jsonType.equals(criterionType)) {
599 criterionFound = true;
600 }
601 }
602 if (!criterionFound) {
603 reason = "criterion " + criterion;
604 return false;
605 }
606 }
607 }
608 return true;
609 }
610
611 @Override
612 public void describeTo(Description description) {
613 description.appendText(reason);
614 }
615 }
616
617 /**
Ray Milkey2b217142014-12-15 09:24:24 -0800618 * Hamcrest matcher to check that an intent is represented properly in a JSON
619 * array of intents.
620 */
621 public static class IntentJsonArrayMatcher extends TypeSafeMatcher<JsonArray> {
622 private final Intent intent;
623 private String reason = "";
624
625 public IntentJsonArrayMatcher(Intent intentValue) {
626 intent = intentValue;
627 }
628
629 @Override
630 public boolean matchesSafely(JsonArray json) {
631 boolean intentFound = false;
Ray Milkeyf7cb4012015-07-20 13:01:07 -0700632 final int expectedAttributes = 5;
Ray Milkey2b217142014-12-15 09:24:24 -0800633 for (int jsonIntentIndex = 0; jsonIntentIndex < json.size();
634 jsonIntentIndex++) {
635
636 final JsonObject jsonIntent = json.get(jsonIntentIndex).asObject();
637
638 if (jsonIntent.names().size() != expectedAttributes) {
639 reason = "Found an intent with the wrong number of attributes";
640 return false;
641 }
642
643 final String jsonIntentId = jsonIntent.get("id").asString();
644 if (jsonIntentId.equals(intent.id().toString())) {
645 intentFound = true;
646
647 // We found the correct intent, check attribute values
648 assertThat(jsonIntent, matchesIntent(intent));
649 }
650 }
651 if (!intentFound) {
652 reason = "Intent with id " + intent.id().toString() + " not found";
653 return false;
654 } else {
655 return true;
656 }
657 }
658
659 @Override
660 public void describeTo(Description description) {
661 description.appendText(reason);
662 }
663 }
664
665 /**
666 * Factory to allocate an intent array matcher.
667 *
668 * @param intent intent object we are looking for
669 * @return matcher
670 */
671 private static IntentJsonArrayMatcher hasIntent(Intent intent) {
672 return new IntentJsonArrayMatcher(intent);
673 }
Ray Milkey4f5de002014-12-17 19:26:11 -0800674
Ray Milkeyed0b1662015-02-05 09:34:29 -0800675 /**
676 * Initializes test mocks and environment.
677 */
Ray Milkey2b217142014-12-15 09:24:24 -0800678 @Before
Ray Milkeyed0b1662015-02-05 09:34:29 -0800679 public void setUpTest() {
Ray Milkey2b217142014-12-15 09:24:24 -0800680 expect(mockIntentService.getIntents()).andReturn(intents).anyTimes();
Ray Milkey1534f8d2015-05-13 15:42:50 -0700681 expect(mockIntentService.getIntentState(anyObject()))
682 .andReturn(IntentState.INSTALLED)
683 .anyTimes();
Ray Milkey2b217142014-12-15 09:24:24 -0800684 // Register the services needed for the test
685 final CodecManager codecService = new CodecManager();
686 codecService.activate();
687 ServiceDirectory testDirectory =
688 new TestServiceDirectory()
689 .add(IntentService.class, mockIntentService)
Author Namee252a002016-09-26 22:42:24 +0530690 .add(FlowRuleService.class, mockFlowService)
Ayaka Koshibec06c89b2015-02-10 19:25:41 -0800691 .add(CodecService.class, codecService)
692 .add(CoreService.class, mockCoreService);
Ray Milkey2b217142014-12-15 09:24:24 -0800693
694 BaseResource.setServiceDirectory(testDirectory);
695
Ray Milkey7c251822016-04-06 17:38:25 -0700696 bindNewGenerator();
Ray Milkey2b217142014-12-15 09:24:24 -0800697 }
698
Ray Milkeyed0b1662015-02-05 09:34:29 -0800699 /**
700 * Tears down and verifies test mocks and environment.
701 */
Ray Milkey2b217142014-12-15 09:24:24 -0800702 @After
Ray Milkeyed0b1662015-02-05 09:34:29 -0800703 public void tearDownTest() {
Ray Milkey2b217142014-12-15 09:24:24 -0800704 verify(mockIntentService);
Ray Milkey2b217142014-12-15 09:24:24 -0800705 }
706
707 /**
708 * Tests the result of the rest api GET when there are no intents.
709 */
710 @Test
711 public void testIntentsEmptyArray() {
712 replay(mockIntentService);
Jian Li9d616492016-03-09 10:52:49 -0800713 final WebTarget wt = target();
714 final String response = wt.path("intents").request().get(String.class);
Ray Milkey2b217142014-12-15 09:24:24 -0800715 assertThat(response, is("{\"intents\":[]}"));
716 }
717
718 /**
719 * Tests the result of the rest api GET when intents are defined.
720 */
721 @Test
722 public void testIntentsArray() {
723 replay(mockIntentService);
724
Ray Milkey43a28222015-02-23 13:57:58 -0800725 final Intent intent1 = new MockIntent(1L, Collections.emptyList());
Ray Milkey2b217142014-12-15 09:24:24 -0800726 final HashSet<NetworkResource> resources = new HashSet<>();
727 resources.add(new MockResource(1));
728 resources.add(new MockResource(2));
729 resources.add(new MockResource(3));
Ray Milkey43a28222015-02-23 13:57:58 -0800730 final Intent intent2 = new MockIntent(2L, resources);
Ray Milkey2b217142014-12-15 09:24:24 -0800731
732 intents.add(intent1);
733 intents.add(intent2);
Jian Li9d616492016-03-09 10:52:49 -0800734 final WebTarget wt = target();
735 final String response = wt.path("intents").request().get(String.class);
Ray Milkey2b217142014-12-15 09:24:24 -0800736 assertThat(response, containsString("{\"intents\":["));
737
Jian Li80cfe452016-01-14 16:04:58 -0800738 final JsonObject result = Json.parse(response).asObject();
Ray Milkey2b217142014-12-15 09:24:24 -0800739 assertThat(result, notNullValue());
740
741 assertThat(result.names(), hasSize(1));
742 assertThat(result.names().get(0), is("intents"));
743
744 final JsonArray jsonIntents = result.get("intents").asArray();
745 assertThat(jsonIntents, notNullValue());
746
747 assertThat(jsonIntents, hasIntent(intent1));
748 assertThat(jsonIntents, hasIntent(intent2));
749 }
750
751 /**
752 * Tests the result of a rest api GET for a single intent.
753 */
754 @Test
755 public void testIntentsSingle() {
756 final HashSet<NetworkResource> resources = new HashSet<>();
757 resources.add(new MockResource(1));
758 resources.add(new MockResource(2));
759 resources.add(new MockResource(3));
Ray Milkey43a28222015-02-23 13:57:58 -0800760 final Intent intent = new MockIntent(3L, resources);
Ray Milkey2b217142014-12-15 09:24:24 -0800761
762 intents.add(intent);
763
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800764 expect(mockIntentService.getIntent(Key.of(0, APP_ID)))
Ray Milkey2b217142014-12-15 09:24:24 -0800765 .andReturn(intent)
766 .anyTimes();
Ayaka Koshibec06c89b2015-02-10 19:25:41 -0800767 expect(mockIntentService.getIntent(Key.of("0", APP_ID)))
768 .andReturn(intent)
769 .anyTimes();
Ray Milkey05b169d2015-08-13 14:33:33 -0700770 expect(mockIntentService.getIntent(Key.of(0, APP_ID)))
771 .andReturn(intent)
772 .anyTimes();
773 expect(mockIntentService.getIntent(Key.of("0x0", APP_ID)))
774 .andReturn(null)
775 .anyTimes();
Ray Milkey2b217142014-12-15 09:24:24 -0800776 replay(mockIntentService);
Ray Milkeyf7cb4012015-07-20 13:01:07 -0700777 expect(mockCoreService.getAppId(APP_ID.name()))
Ayaka Koshibec06c89b2015-02-10 19:25:41 -0800778 .andReturn(APP_ID).anyTimes();
779 replay(mockCoreService);
Jian Li9d616492016-03-09 10:52:49 -0800780 final WebTarget wt = target();
Ray Milkey05b169d2015-08-13 14:33:33 -0700781
782 // Test get using key string
Jian Li9d616492016-03-09 10:52:49 -0800783 final String response = wt.path("intents/" + APP_ID.name()
784 + "/0").request().get(String.class);
Jian Li80cfe452016-01-14 16:04:58 -0800785 final JsonObject result = Json.parse(response).asObject();
Ray Milkey2b217142014-12-15 09:24:24 -0800786 assertThat(result, matchesIntent(intent));
Ray Milkey05b169d2015-08-13 14:33:33 -0700787
788 // Test get using numeric value
Jian Li9d616492016-03-09 10:52:49 -0800789 final String responseNumeric = wt.path("intents/" + APP_ID.name()
790 + "/0x0").request().get(String.class);
Jian Li80cfe452016-01-14 16:04:58 -0800791 final JsonObject resultNumeric = Json.parse(responseNumeric).asObject();
Ray Milkey05b169d2015-08-13 14:33:33 -0700792 assertThat(resultNumeric, matchesIntent(intent));
Ray Milkey2b217142014-12-15 09:24:24 -0800793 }
794
795 /**
Author Namee252a002016-09-26 22:42:24 +0530796 * Tests the result of a rest api GET for related flows for single intent.
797 */
798 @Test
799 public void testRelatedFlowsForIntents() {
800 List<FlowEntry> flowEntries = new ArrayList<>();
801 flowEntries.add(flow1);
802 flowEntries.add(flow2);
803 List<List<FlowEntry>> paths = new ArrayList<>();
804 paths.add(flowEntries);
805 List<FlowRule> flowRules = new ArrayList<>();
806 flowRules.add(flowRule1);
807 flowRules.add(flowRule2);
808 FlowRuleIntent flowRuleIntent = new FlowRuleIntent(
809 APP_ID,
810 flowRules,
811 new HashSet<NetworkResource>());
812 Intent intent = new MockIntent(3L);
813 installableIntents.add(flowRuleIntent);
814 intents.add(intent);
815
816 expect(mockIntentService.getIntent(Key.of(0, APP_ID)))
817 .andReturn(intent)
818 .anyTimes();
819 expect(mockIntentService.getIntent(Key.of("0", APP_ID)))
820 .andReturn(intent)
821 .anyTimes();
822 expect(mockIntentService.getIntent(Key.of(0, APP_ID)))
823 .andReturn(intent)
824 .anyTimes();
825 expect(mockIntentService.getIntent(Key.of("0x0", APP_ID)))
826 .andReturn(null)
827 .anyTimes();
828 expect(mockIntentService.getInstallableIntents(intent.key()))
829 .andReturn(installableIntents)
830 .anyTimes();
831 replay(mockIntentService);
832
833 expect(mockFlowService.getFlowEntries(deviceId1))
834 .andReturn(flowEntries).anyTimes();
835 replay(mockFlowService);
836
837 expect(mockCoreService.getAppId(APP_ID.name()))
838 .andReturn(APP_ID).anyTimes();
839 expect(mockCoreService.getAppId(APP_ID.id()))
840 .andReturn(APP_ID).anyTimes();
841 replay(mockCoreService);
842
843 final WebTarget wt = target();
844
845 // Test get using key string
846 final String response = wt.path("intents/relatedflows/" + APP_ID.name()
847 + "/0").request().get(String.class);
848 final JsonObject result = Json.parse(response).asObject();
849 assertThat(result, matchesRelatedFlowEntries(paths, APP_ID.name()));
850
851 // Test get using numeric value
852 final String responseNumeric = wt.path("intents/relatedflows/" + APP_ID.name()
853 + "/0x0").request().get(String.class);
854 final JsonObject resultNumeric = Json.parse(responseNumeric).asObject();
855 assertThat(resultNumeric, matchesRelatedFlowEntries(paths, APP_ID.name()));
856 }
857
858 /**
Ray Milkey2b217142014-12-15 09:24:24 -0800859 * Tests that a fetch of a non-existent intent object throws an exception.
860 */
861 @Test
862 public void testBadGet() {
863
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800864 expect(mockIntentService.getIntent(Key.of(0, APP_ID)))
Ray Milkey2b217142014-12-15 09:24:24 -0800865 .andReturn(null)
866 .anyTimes();
867 replay(mockIntentService);
868
Jian Li9d616492016-03-09 10:52:49 -0800869 WebTarget wt = target();
Ray Milkey2b217142014-12-15 09:24:24 -0800870 try {
Jian Li9d616492016-03-09 10:52:49 -0800871 wt.path("intents/0").request().get(String.class);
Ray Milkey2b217142014-12-15 09:24:24 -0800872 fail("Fetch of non-existent intent did not throw an exception");
Jian Li9d616492016-03-09 10:52:49 -0800873 } catch (NotFoundException ex) {
Ray Milkey2b217142014-12-15 09:24:24 -0800874 assertThat(ex.getMessage(),
Jian Li9d616492016-03-09 10:52:49 -0800875 containsString("HTTP 404 Not Found"));
Ray Milkey2b217142014-12-15 09:24:24 -0800876 }
877 }
Ray Milkeyb82c42b2015-06-30 09:42:20 -0700878
879 /**
880 * Tests creating an intent with POST.
881 */
882 @Test
883 public void testPost() {
Ray Milkeyf7cb4012015-07-20 13:01:07 -0700884 ApplicationId testId = new DefaultApplicationId(2, "myApp");
885 expect(mockCoreService.getAppId("myApp"))
886 .andReturn(testId);
Ray Milkeyb82c42b2015-06-30 09:42:20 -0700887 replay(mockCoreService);
888
889 mockIntentService.submit(anyObject());
890 expectLastCall();
891 replay(mockIntentService);
892
893 InputStream jsonStream = IntentsResourceTest.class
894 .getResourceAsStream("post-intent.json");
Jian Li9d616492016-03-09 10:52:49 -0800895 WebTarget wt = target();
Ray Milkeyb82c42b2015-06-30 09:42:20 -0700896
Jian Li9d616492016-03-09 10:52:49 -0800897 Response response = wt.path("intents")
898 .request(MediaType.APPLICATION_JSON_TYPE)
899 .post(Entity.json(jsonStream));
Ray Milkeyb82c42b2015-06-30 09:42:20 -0700900 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
901 String location = response.getLocation().getPath();
Ray Milkey8d076402015-08-31 15:43:18 -0700902 assertThat(location, Matchers.startsWith("/intents/myApp/"));
Ray Milkeyb82c42b2015-06-30 09:42:20 -0700903 }
Ray Milkey7b158512015-07-21 16:32:43 -0700904
905 /**
Ray Milkey05b169d2015-08-13 14:33:33 -0700906 * Tests creating an intent with POST and illegal JSON.
907 */
908 @Test
909 public void testBadPost() {
910 replay(mockCoreService);
911 replay(mockIntentService);
912
913 String json = "this is invalid!";
Jian Li9d616492016-03-09 10:52:49 -0800914 WebTarget wt = target();
Ray Milkey05b169d2015-08-13 14:33:33 -0700915
Jian Li9d616492016-03-09 10:52:49 -0800916 Response response = wt.path("intents")
917 .request(MediaType.APPLICATION_JSON_TYPE)
918 .post(Entity.json(json));
Ray Milkey05b169d2015-08-13 14:33:33 -0700919 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_BAD_REQUEST));
920 }
921
922 /**
Ray Milkey7b158512015-07-21 16:32:43 -0700923 * Tests removing an intent with DELETE.
924 */
925 @Test
926 public void testRemove() {
927 final HashSet<NetworkResource> resources = new HashSet<>();
928 resources.add(new MockResource(1));
929 resources.add(new MockResource(2));
930 resources.add(new MockResource(3));
931 final Intent intent = new MockIntent(3L, resources);
932 final ApplicationId appId = new DefaultApplicationId(2, "app");
933 IntentService fakeManager = new FakeIntentManager();
934
935 expect(mockCoreService.getAppId("app"))
936 .andReturn(appId).once();
937 replay(mockCoreService);
938
939 mockIntentService.withdraw(anyObject());
940 expectLastCall().andDelegateTo(fakeManager).once();
941 expect(mockIntentService.getIntent(Key.of(2, appId)))
942 .andReturn(intent)
943 .once();
944 expect(mockIntentService.getIntent(Key.of("0x2", appId)))
945 .andReturn(null)
946 .once();
947
948 mockIntentService.addListener(anyObject());
949 expectLastCall().andDelegateTo(fakeManager).once();
950 mockIntentService.removeListener(anyObject());
951 expectLastCall().andDelegateTo(fakeManager).once();
952
953 replay(mockIntentService);
954
Jian Li9d616492016-03-09 10:52:49 -0800955 WebTarget wt = target();
Ray Milkey7b158512015-07-21 16:32:43 -0700956
Jian Li9d616492016-03-09 10:52:49 -0800957 Response response = wt.path("intents/app/0x2")
Ray Milkey7c251822016-04-06 17:38:25 -0700958 .request(MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN)
Jian Li9d616492016-03-09 10:52:49 -0800959 .delete();
Ray Milkey7b158512015-07-21 16:32:43 -0700960 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NO_CONTENT));
961 }
Ray Milkey05b169d2015-08-13 14:33:33 -0700962
963 /**
964 * Tests removal of a non existent intent with DELETE.
965 */
966 @Test
967 public void testBadRemove() {
968 final ApplicationId appId = new DefaultApplicationId(2, "app");
969
970 expect(mockCoreService.getAppId("app"))
971 .andReturn(appId).once();
972 replay(mockCoreService);
973
974 expect(mockIntentService.getIntent(Key.of(2, appId)))
975 .andReturn(null)
976 .once();
977 expect(mockIntentService.getIntent(Key.of("0x2", appId)))
978 .andReturn(null)
979 .once();
980
981 replay(mockIntentService);
982
Jian Li9d616492016-03-09 10:52:49 -0800983 WebTarget wt = target();
Ray Milkey05b169d2015-08-13 14:33:33 -0700984
Jian Li9d616492016-03-09 10:52:49 -0800985 Response response = wt.path("intents/app/0x2")
Ray Milkey7c251822016-04-06 17:38:25 -0700986 .request(MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN)
Jian Li9d616492016-03-09 10:52:49 -0800987 .delete();
Ray Milkey05b169d2015-08-13 14:33:33 -0700988 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NO_CONTENT));
989 }
990
Ray Milkey2b217142014-12-15 09:24:24 -0800991}