blob: b9b5dbd75cf6d3cfcc02cab7cc697e58f200d65b [file] [log] [blame]
Ray Milkey2b217142014-12-15 09:24:24 -08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
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;
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +020022import com.fasterxml.jackson.databind.node.ObjectNode;
Ray Milkey2b217142014-12-15 09:24:24 -080023import org.hamcrest.Description;
Ray Milkeyb82c42b2015-06-30 09:42:20 -070024import org.hamcrest.Matchers;
Ray Milkey2b217142014-12-15 09:24:24 -080025import org.hamcrest.TypeSafeMatcher;
26import org.junit.After;
27import org.junit.Before;
28import org.junit.Test;
29import org.onlab.osgi.ServiceDirectory;
30import org.onlab.osgi.TestServiceDirectory;
Author Namee252a002016-09-26 22:42:24 +053031import org.onlab.packet.MacAddress;
Ray Milkey2b217142014-12-15 09:24:24 -080032import org.onlab.rest.BaseResource;
33import org.onosproject.codec.CodecService;
34import org.onosproject.codec.impl.CodecManager;
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +020035import org.onosproject.codec.impl.MockCodecContext;
Ray Milkey2b217142014-12-15 09:24:24 -080036import org.onosproject.core.ApplicationId;
Ayaka Koshibec06c89b2015-02-10 19:25:41 -080037import org.onosproject.core.CoreService;
Ray Milkey2b217142014-12-15 09:24:24 -080038import org.onosproject.core.DefaultApplicationId;
Author Namee252a002016-09-26 22:42:24 +053039import org.onosproject.core.GroupId;
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +020040import org.onosproject.net.ConnectPoint;
41import org.onosproject.net.DefaultLink;
Author Namee252a002016-09-26 22:42:24 +053042import org.onosproject.net.DeviceId;
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +020043import org.onosproject.net.Link;
Ray Milkey2b217142014-12-15 09:24:24 -080044import org.onosproject.net.NetworkResource;
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +020045import org.onosproject.net.PortNumber;
Author Namee252a002016-09-26 22:42:24 +053046import org.onosproject.net.flow.DefaultTrafficSelector;
47import org.onosproject.net.flow.DefaultTrafficTreatment;
48import org.onosproject.net.flow.FlowEntry;
Ray Milkey634eb172017-04-05 14:48:50 -070049import org.onosproject.net.flow.FlowEntryAdapter;
Author Namee252a002016-09-26 22:42:24 +053050import org.onosproject.net.flow.FlowId;
51import org.onosproject.net.flow.FlowRule;
52import org.onosproject.net.flow.FlowRuleExtPayLoad;
53import org.onosproject.net.flow.FlowRuleService;
Carmelo Cascone41605742017-06-19 15:46:44 +090054import org.onosproject.net.flow.TableId;
Author Namee252a002016-09-26 22:42:24 +053055import org.onosproject.net.flow.TrafficSelector;
56import org.onosproject.net.flow.TrafficTreatment;
57import org.onosproject.net.flow.criteria.Criterion;
58import org.onosproject.net.flow.instructions.Instruction;
Ray Milkey7b158512015-07-21 16:32:43 -070059import org.onosproject.net.intent.FakeIntentManager;
Author Namee252a002016-09-26 22:42:24 +053060import org.onosproject.net.intent.FlowRuleIntent;
Ray Milkey2b217142014-12-15 09:24:24 -080061import org.onosproject.net.intent.Intent;
Ray Milkey2b217142014-12-15 09:24:24 -080062import org.onosproject.net.intent.IntentService;
Ray Milkey1534f8d2015-05-13 15:42:50 -070063import org.onosproject.net.intent.IntentState;
Ray Milkeyf9af43c2015-02-09 16:45:48 -080064import org.onosproject.net.intent.Key;
Thomas Vachuska2048c1f2017-05-10 19:32:22 -070065import org.onosproject.net.intent.MockIdGenerator;
Ray Milkey39f78b62018-01-05 15:17:37 -080066import org.onosproject.net.intent.PathIntent;
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +020067import org.onosproject.net.provider.ProviderId;
Ray Milkey2b217142014-12-15 09:24:24 -080068
dvaddire95c84ed2017-06-14 15:42:24 +053069
Author Namee252a002016-09-26 22:42:24 +053070import javax.ws.rs.NotFoundException;
71import javax.ws.rs.client.Entity;
72import javax.ws.rs.client.WebTarget;
73import javax.ws.rs.core.MediaType;
74import javax.ws.rs.core.Response;
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +020075import java.io.IOException;
Author Namee252a002016-09-26 22:42:24 +053076import java.io.InputStream;
77import java.net.HttpURLConnection;
78import java.util.ArrayList;
79import java.util.Collections;
80import java.util.HashSet;
81import java.util.List;
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +020082import java.util.Set;
Author Namee252a002016-09-26 22:42:24 +053083import java.util.concurrent.TimeUnit;
Ray Milkey2b217142014-12-15 09:24:24 -080084
Author Namee252a002016-09-26 22:42:24 +053085import static java.util.concurrent.TimeUnit.SECONDS;
86import static org.easymock.EasyMock.*;
87import static org.hamcrest.Matchers.*;
Ray Milkey2b217142014-12-15 09:24:24 -080088import static org.junit.Assert.assertThat;
89import static org.junit.Assert.fail;
Ray Milkey43a28222015-02-23 13:57:58 -080090import static org.onosproject.net.intent.IntentTestsMocks.MockIntent;
Ray Milkey2b217142014-12-15 09:24:24 -080091
92/**
93 * Unit tests for Intents REST APIs.
94 */
Ray Milkey9c3d3362015-01-28 10:39:56 -080095public class IntentsResourceTest extends ResourceTest {
Author Namee252a002016-09-26 22:42:24 +053096
97
98 private static final String APPID = "appId";
99 private static final String CRITERIA = "criteria";
100 private static final String DEVICE_ID = "deviceId";
101 private static final String ID = "id";
102 private static final String INSTRUCTIONS = "instructions";
103 private static final String PATHS = "paths";
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +0200104 private static final String INSTALLABLES = "installables";
105 private static final String RESOURCES = "resources";
106 private static final String DEVICE = "device";
107 private static final String PORT = "port";
108 private static final String SRC = "src";
109 private static final String DST = "dst";
Author Namee252a002016-09-26 22:42:24 +0530110 private static final String SELECTOR = "selector";
111 private static final String SPACE = " ";
112 private static final String TREATMENT = "treatment";
113 private static final String TYPE = "type";
114
Ray Milkey2b217142014-12-15 09:24:24 -0800115 final IntentService mockIntentService = createMock(IntentService.class);
Ayaka Koshibec06c89b2015-02-10 19:25:41 -0800116 final CoreService mockCoreService = createMock(CoreService.class);
Author Namee252a002016-09-26 22:42:24 +0530117 final FlowRuleService mockFlowService = createMock(FlowRuleService.class);
Ray Milkey2b217142014-12-15 09:24:24 -0800118 final HashSet<Intent> intents = new HashSet<>();
Author Namee252a002016-09-26 22:42:24 +0530119 final List<org.onosproject.net.intent.Intent> installableIntents = new ArrayList<>();
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800120 private static final ApplicationId APP_ID = new DefaultApplicationId(1, "test");
Ray Milkey2b217142014-12-15 09:24:24 -0800121
Author Namee252a002016-09-26 22:42:24 +0530122 final DeviceId deviceId1 = DeviceId.deviceId("1");
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +0200123 final DeviceId deviceId2 = DeviceId.deviceId("2");
124 final DeviceId deviceId3 = DeviceId.deviceId("3");
125
126 final ConnectPoint connectPoint1 = new ConnectPoint(deviceId1, PortNumber.portNumber(1L));
127 final ConnectPoint connectPoint2 = new ConnectPoint(deviceId2, PortNumber.portNumber(1L));
128 final ConnectPoint connectPoint3 = new ConnectPoint(deviceId2, PortNumber.portNumber(2L));
129 final ConnectPoint connectPoint4 = new ConnectPoint(deviceId3, PortNumber.portNumber(1L));
Author Namee252a002016-09-26 22:42:24 +0530130
131 final TrafficTreatment treatment1 = DefaultTrafficTreatment.builder()
132 .setEthDst(MacAddress.BROADCAST)
133 .build();
134 final TrafficTreatment treatment2 = DefaultTrafficTreatment.builder()
135 .setEthDst(MacAddress.IPV4_MULTICAST)
136 .build();
137
138 final TrafficSelector selector1 = DefaultTrafficSelector.builder()
139 .matchEthType((short) 3)
140 .matchIPProtocol((byte) 9)
141 .build();
142 final TrafficSelector selector2 = DefaultTrafficSelector.builder()
143 .matchEthType((short) 4)
144 .matchIPProtocol((byte) 10)
145 .build();
146
147 final MockFlowEntry flow1 = new MockFlowEntry(deviceId1, 1, treatment1, selector1);
148 final MockFlowEntry flow2 = new MockFlowEntry(deviceId1, 2, treatment2, selector2);
149
150 final MockFlowRule flowRule1 = new MockFlowRule(deviceId1, 1, treatment1, selector1);
151 final MockFlowRule flowRule2 = new MockFlowRule(deviceId1, 2, treatment2, selector2);
152
Ray Milkey2b217142014-12-15 09:24:24 -0800153 private class MockResource implements NetworkResource {
154 int id;
155
156 MockResource(int id) {
157 this.id = id;
158 }
159
Ayaka Koshibec06c89b2015-02-10 19:25:41 -0800160 @Override
Ray Milkey2b217142014-12-15 09:24:24 -0800161 public String toString() {
162 return "Resource " + Integer.toString(id);
163 }
164 }
165
Ray Milkey2b217142014-12-15 09:24:24 -0800166 /**
Author Namee252a002016-09-26 22:42:24 +0530167 * Mock class for a flow entry.
168 */
Ray Milkey634eb172017-04-05 14:48:50 -0700169 private static class MockFlowEntry extends FlowEntryAdapter {
Author Namee252a002016-09-26 22:42:24 +0530170 final DeviceId deviceId;
171 final long baseValue;
172 TrafficTreatment treatment;
173 TrafficSelector selector;
174
175 public MockFlowEntry(DeviceId deviceId, long id,
176 TrafficTreatment treatment,
177 TrafficSelector selector) {
178 this.deviceId = deviceId;
179 this.baseValue = id * 100;
180 this.treatment = treatment;
181 this.selector = selector;
182 }
183
184 @Override
Author Namee252a002016-09-26 22:42:24 +0530185 public long life() {
186 return life(SECONDS);
187 }
188
189 @Override
kalagesa42019542017-03-14 18:00:47 +0530190 public FlowLiveType liveType() {
191 return FlowLiveType.IMMEDIATE;
192 }
193
194 @Override
Author Namee252a002016-09-26 22:42:24 +0530195 public long life(TimeUnit timeUnit) {
196 return SECONDS.convert(baseValue + 11, timeUnit);
197 }
198
199 @Override
200 public long packets() {
201 return baseValue + 22;
202 }
203
204 @Override
205 public long bytes() {
206 return baseValue + 33;
207 }
208
209 @Override
210 public long lastSeen() {
211 return baseValue + 44;
212 }
213
214 @Override
Author Namee252a002016-09-26 22:42:24 +0530215 public FlowId id() {
216 final long id = baseValue + 55;
217 return FlowId.valueOf(id);
218 }
219
220 @Override
221 public GroupId groupId() {
Yi Tsengfa394de2017-02-01 11:26:40 -0800222 return new GroupId(3);
Author Namee252a002016-09-26 22:42:24 +0530223 }
224
225 @Override
226 public short appId() {
227 return 1;
228 }
229
230 @Override
231 public int priority() {
232 return (int) (baseValue + 66);
233 }
234
235 @Override
236 public DeviceId deviceId() {
237 return deviceId;
238 }
239
240 @Override
241 public TrafficSelector selector() {
242 return selector;
243 }
244
245 @Override
246 public TrafficTreatment treatment() {
247 return treatment;
248 }
249
250 @Override
251 public int timeout() {
252 return (int) (baseValue + 77);
253 }
254
Author Namee252a002016-09-26 22:42:24 +0530255
256 @Override
257 public boolean exactMatch(FlowRule rule) {
258 return this.appId() == rule.appId() &&
259 this.deviceId().equals(rule.deviceId()) &&
260 this.id().equals(rule.id()) &&
261 this.treatment.equals(rule.treatment()) &&
262 this.selector().equals(rule.selector());
263 }
264
265 @Override
Author Namee252a002016-09-26 22:42:24 +0530266 public String toString() {
267 return id().id().toString();
268 }
269 }
270
271 /**
272 * Mock class for a flow rule.
273 */
274 private static class MockFlowRule implements FlowRule {
275
276 final DeviceId deviceId;
277 final long baseValue;
278 TrafficTreatment treatment;
279 TrafficSelector selector;
280
281 public MockFlowRule(DeviceId deviceId,
282 long id,
283 TrafficTreatment treatment,
284 TrafficSelector selector) {
285 this.deviceId = deviceId;
286 this.baseValue = id * 100;
287 this.treatment = treatment;
288 this.selector = selector;
289 }
290
291 @Override
292 public FlowId id() {
293 long id = baseValue + 55;
294 return FlowId.valueOf(id);
295 }
296
297 @Override
298 public short appId() {
299 return 1;
300 }
301
302 @Override
303 public GroupId groupId() {
Yi Tsengfa394de2017-02-01 11:26:40 -0800304 return new GroupId(3);
Author Namee252a002016-09-26 22:42:24 +0530305 }
306
307 @Override
308 public int priority() {
309 return 0;
310 }
311
312 @Override
313 public DeviceId deviceId() {
314 return deviceId;
315 }
316
317 @Override
318 public TrafficSelector selector() {
319 return selector;
320 }
321
322 @Override
323 public TrafficTreatment treatment() {
324 return treatment;
325 }
326
327 @Override
328 public int timeout() {
329 return (int) (baseValue + 77);
330 }
331
332 @Override
333 public int hardTimeout() {
334 return 0;
335 }
336
337 @Override
338 public FlowRemoveReason reason() {
339 return FlowRemoveReason.NO_REASON;
340 }
341
342 @Override
343 public boolean isPermanent() {
344 return false;
345 }
346
347 @Override
348 public int tableId() {
349 return 0;
350 }
351
352 @Override
Carmelo Cascone41605742017-06-19 15:46:44 +0900353 public TableId table() {
354 return DEFAULT_TABLE;
355 }
356
357 @Override
Author Namee252a002016-09-26 22:42:24 +0530358 public boolean exactMatch(FlowRule rule) {
359 return false;
360 }
361
362 @Override
363 public FlowRuleExtPayLoad payLoad() {
364 return null;
365 }
366 }
367
368 /**
Ray Milkey2b217142014-12-15 09:24:24 -0800369 * Hamcrest matcher to check that an intent representation in JSON matches
370 * the actual intent.
371 */
372 public static class IntentJsonMatcher extends TypeSafeMatcher<JsonObject> {
373 private final Intent intent;
374 private String reason = "";
375
376 public IntentJsonMatcher(Intent intentValue) {
377 intent = intentValue;
378 }
379
380 @Override
381 public boolean matchesSafely(JsonObject jsonIntent) {
382 // check id
383 final String jsonId = jsonIntent.get("id").asString();
384 if (!jsonId.equals(intent.id().toString())) {
385 reason = "id " + intent.id().toString();
386 return false;
387 }
388
389 // check application id
Ray Milkeyf7cb4012015-07-20 13:01:07 -0700390
Ray Milkey2b217142014-12-15 09:24:24 -0800391 final String jsonAppId = jsonIntent.get("appId").asString();
Ray Milkeyf7cb4012015-07-20 13:01:07 -0700392 final String appId = intent.appId().name();
393 if (!jsonAppId.equals(appId)) {
394 reason = "appId was " + jsonAppId;
Ray Milkey2b217142014-12-15 09:24:24 -0800395 return false;
396 }
397
398 // check intent type
399 final String jsonType = jsonIntent.get("type").asString();
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +0200400 if (!intent.getClass().getSimpleName().equals(jsonType)) {
Ray Milkey2b217142014-12-15 09:24:24 -0800401 reason = "type MockIntent";
402 return false;
403 }
404
Ray Milkey1534f8d2015-05-13 15:42:50 -0700405 // check state field
406 final String jsonState = jsonIntent.get("state").asString();
Jon Halla3fcf672017-03-28 16:53:22 -0700407 if (!"INSTALLED".equals(jsonState)) {
Ray Milkey1534f8d2015-05-13 15:42:50 -0700408 reason = "state INSTALLED";
409 return false;
410 }
411
Ray Milkey2b217142014-12-15 09:24:24 -0800412 // check resources array
413 final JsonArray jsonResources = jsonIntent.get("resources").asArray();
414 if (intent.resources() != null) {
415 if (intent.resources().size() != jsonResources.size()) {
416 reason = "resources array size of " + Integer.toString(intent.resources().size());
417 return false;
418 }
419 for (final NetworkResource resource : intent.resources()) {
420 boolean resourceFound = false;
421 final String resourceString = resource.toString();
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +0200422
423 if (resource instanceof Link) {
424 final Link resourceLink = (Link) resource;
425 MockCodecContext codecContext = new MockCodecContext();
426
427 for (int resourceIndex = 0; resourceIndex < jsonResources.size(); resourceIndex++) {
428 final ObjectNode value;
429 try {
430 value = (ObjectNode) codecContext.mapper()
431 .readTree(jsonResources.get(resourceIndex).toString());
432 } catch (IOException e) {
433 reason = "bad json";
434 return false;
435 }
436 final Link link = codecContext.codec(Link.class).decode(value, codecContext);
437 if (resourceLink.equals(link)) {
438 resourceFound = true;
439 }
440 }
441 } else {
442
443 for (int resourceIndex = 0; resourceIndex < jsonResources.size(); resourceIndex++) {
444 final JsonValue value = jsonResources.get(resourceIndex);
445 if (value.asString().equals(resourceString)) {
446 resourceFound = true;
447 }
Ray Milkey2b217142014-12-15 09:24:24 -0800448 }
449 }
450 if (!resourceFound) {
451 reason = "resource " + resourceString;
452 return false;
453 }
454 }
455 } else if (jsonResources.size() != 0) {
456 reason = "resources array empty";
457 return false;
458 }
459 return true;
460 }
461
462 @Override
463 public void describeTo(Description description) {
464 description.appendText(reason);
465 }
466 }
467
468 /**
469 * Factory to allocate an intent matcher.
470 *
471 * @param intent intent object we are looking for
472 * @return matcher
473 */
474 private static IntentJsonMatcher matchesIntent(Intent intent) {
475 return new IntentJsonMatcher(intent);
476 }
477
478 /**
Author Namee252a002016-09-26 22:42:24 +0530479 * Factory to allocate an IntentRelatedFlows matcher.
480 *
dvaddire95c84ed2017-06-14 15:42:24 +0530481 * @param pathEntries list of path conatining flow entries of a particular intent
Author Namee252a002016-09-26 22:42:24 +0530482 * @param expectedAppId expected app id we are looking for
483 * @return matcher
484 */
485 private static IntentStatsJsonMatcher matchesRelatedFlowEntries(
486 List<List<FlowEntry>> pathEntries,
487 final String expectedAppId) {
488 return new IntentStatsJsonMatcher(pathEntries, expectedAppId);
489 }
490
491 /**
492 * Hamcrest matcher to check that an list of flowEntries in JSON matches
493 * the actual list of flow entries.
494 */
495 public static class IntentStatsJsonMatcher extends
496 TypeSafeMatcher<JsonObject> {
497
498 private final List<List<FlowEntry>> pathEntries;
499 private final String expectedAppId;
500 private String reason = "";
501
502 public IntentStatsJsonMatcher(
503 final List<List<FlowEntry>> pathEntries,
504 final String expectedAppId) {
505 this.pathEntries = pathEntries;
506 this.expectedAppId = expectedAppId;
507 }
508
509 @Override
510 public boolean matchesSafely(JsonObject jsonIntent) {
511 int jsonPathIndex = 0;
512 JsonArray jsonPaths = jsonIntent.get(PATHS).asArray();
513
514 if (pathEntries != null) {
515
rohitsharanfd747602017-01-23 21:57:28 +0530516 if (pathEntries.size() == 0) {
517 reason = "pathEntries array empty";
518 return false;
519 }
520
Author Namee252a002016-09-26 22:42:24 +0530521 if (pathEntries.size() != jsonPaths.size()) {
522 reason = "path entries array size of " +
523 Integer.toString(pathEntries.size());
524 return false;
525 }
526
527 for (List<FlowEntry> flowEntries : pathEntries) {
528 JsonArray jsonFlowEntries = jsonPaths.get(
529 jsonPathIndex++).asArray();
530
531 if (flowEntries.size() != jsonFlowEntries.size()) {
532 reason = "flow entries array size of " +
533 Integer.toString(pathEntries.size());
534
535 return false;
536 }
537
538 int jsonFlowEntryIndex = 0;
539 for (FlowEntry flow : flowEntries) {
540
541 JsonObject jsonFlow = jsonFlowEntries.get(
542 jsonFlowEntryIndex++).asObject();
543
544 String jsonId = jsonFlow.get(ID).asString();
545 String flowId = Long.toString(flow.id().value());
546 if (!jsonId.equals(flowId)) {
547 reason = ID + SPACE + flow.id();
548 return false;
549 }
550
551 // check application id
552 String jsonAppId = jsonFlow.get(APPID).asString();
553 if (!jsonAppId.equals(expectedAppId)) {
554 reason = APPID + SPACE + Short.toString(flow.appId());
555 return false;
556 }
557
558 // check device id
559 String jsonDeviceId =
560 jsonFlow.get(DEVICE_ID).asString();
561
562 if (!jsonDeviceId.equals(flow.deviceId().toString())) {
563 reason = DEVICE_ID + SPACE + flow.deviceId();
564 return false;
565 }
566
567 if (!checkFlowTreatment(flow, jsonFlow)) {
568 return false;
569 }
570
571 if (!checkFlowSelector(flow, jsonFlow)) {
572 return false;
573 }
574
575 }
576
577 }
rohitsharanfd747602017-01-23 21:57:28 +0530578 } else {
Author Namee252a002016-09-26 22:42:24 +0530579 reason = "pathEntries array empty";
580 return false;
581 }
582
583 return true;
584 }
585
586 // check treatment and instructions array.
587 private boolean checkFlowTreatment(FlowEntry flow, JsonObject jsonFlow) {
588
589 if (flow.treatment() != null) {
590 JsonObject jsonTreatment =
591 jsonFlow.get(TREATMENT).asObject();
592 JsonArray jsonInstructions =
593 jsonTreatment.get(INSTRUCTIONS).asArray();
594
595 if (flow.treatment().immediate().size() !=
596 jsonInstructions.size()) {
597 reason = "instructions array size of " +
598 flow.treatment().immediate().size();
599
600 return false;
601 }
602 for (Instruction instruction :
603 flow.treatment().immediate()) {
604 boolean instructionFound = false;
605 for (int instructionIndex = 0;
606 instructionIndex < jsonInstructions.size();
607 instructionIndex++) {
608 String jsonType =
609 jsonInstructions.get(instructionIndex)
610 .asObject().get(TYPE).asString();
611
612 String instructionType =
613 instruction.type().name();
614
615 if (jsonType.equals(instructionType)) {
616 instructionFound = true;
617 }
618 }
619 if (!instructionFound) {
620 reason = INSTRUCTIONS + SPACE + instruction;
621 return false;
622 }
623 }
624 }
625 return true;
626 }
627
628 // check selector and criteria array.
629 private boolean checkFlowSelector(FlowEntry flow, JsonObject jsonFlow) {
630
631 if (flow.selector() != null) {
632 JsonObject jsonTreatment =
633 jsonFlow.get(SELECTOR).asObject();
634
635 JsonArray jsonCriteria =
636 jsonTreatment.get(CRITERIA).asArray();
637
638 if (flow.selector().criteria().size() != jsonCriteria.size()) {
639 reason = CRITERIA + " array size of " +
640 Integer.toString(flow.selector().criteria().size());
641 return false;
642 }
643 for (Criterion criterion : flow.selector().criteria()) {
644 boolean criterionFound = false;
645
646 for (int criterionIndex = 0;
647 criterionIndex < jsonCriteria.size();
648 criterionIndex++) {
649 String jsonType =
650 jsonCriteria.get(criterionIndex)
651 .asObject().get(TYPE).asString();
652 String criterionType = criterion.type().name();
653 if (jsonType.equals(criterionType)) {
654 criterionFound = true;
655 }
656 }
657 if (!criterionFound) {
658 reason = "criterion " + criterion;
659 return false;
660 }
661 }
662 }
663 return true;
664 }
665
666 @Override
667 public void describeTo(Description description) {
668 description.appendText(reason);
669 }
670 }
671
672 /**
Ray Milkey2b217142014-12-15 09:24:24 -0800673 * Hamcrest matcher to check that an intent is represented properly in a JSON
674 * array of intents.
675 */
676 public static class IntentJsonArrayMatcher extends TypeSafeMatcher<JsonArray> {
677 private final Intent intent;
678 private String reason = "";
679
680 public IntentJsonArrayMatcher(Intent intentValue) {
681 intent = intentValue;
682 }
683
684 @Override
685 public boolean matchesSafely(JsonArray json) {
686 boolean intentFound = false;
Antonio Marsico4f68ec92017-03-09 11:16:32 +0100687 final int expectedAttributes = 6;
Ray Milkey2b217142014-12-15 09:24:24 -0800688 for (int jsonIntentIndex = 0; jsonIntentIndex < json.size();
689 jsonIntentIndex++) {
690
691 final JsonObject jsonIntent = json.get(jsonIntentIndex).asObject();
692
693 if (jsonIntent.names().size() != expectedAttributes) {
694 reason = "Found an intent with the wrong number of attributes";
695 return false;
696 }
697
698 final String jsonIntentId = jsonIntent.get("id").asString();
699 if (jsonIntentId.equals(intent.id().toString())) {
700 intentFound = true;
701
702 // We found the correct intent, check attribute values
703 assertThat(jsonIntent, matchesIntent(intent));
704 }
705 }
706 if (!intentFound) {
707 reason = "Intent with id " + intent.id().toString() + " not found";
708 return false;
709 } else {
710 return true;
711 }
712 }
713
714 @Override
715 public void describeTo(Description description) {
716 description.appendText(reason);
717 }
718 }
719
720 /**
721 * Factory to allocate an intent array matcher.
722 *
723 * @param intent intent object we are looking for
724 * @return matcher
725 */
726 private static IntentJsonArrayMatcher hasIntent(Intent intent) {
727 return new IntentJsonArrayMatcher(intent);
728 }
Ray Milkey4f5de002014-12-17 19:26:11 -0800729
Ray Milkeyed0b1662015-02-05 09:34:29 -0800730 /**
731 * Initializes test mocks and environment.
732 */
Ray Milkey2b217142014-12-15 09:24:24 -0800733 @Before
Ray Milkeyed0b1662015-02-05 09:34:29 -0800734 public void setUpTest() {
Ray Milkey2b217142014-12-15 09:24:24 -0800735 expect(mockIntentService.getIntents()).andReturn(intents).anyTimes();
Ray Milkey1534f8d2015-05-13 15:42:50 -0700736 expect(mockIntentService.getIntentState(anyObject()))
737 .andReturn(IntentState.INSTALLED)
738 .anyTimes();
Ray Milkey2b217142014-12-15 09:24:24 -0800739 // Register the services needed for the test
dvaddire95c84ed2017-06-14 15:42:24 +0530740 final CodecManager codecService = new CodecManager();
Ray Milkey2b217142014-12-15 09:24:24 -0800741 codecService.activate();
742 ServiceDirectory testDirectory =
743 new TestServiceDirectory()
744 .add(IntentService.class, mockIntentService)
Author Namee252a002016-09-26 22:42:24 +0530745 .add(FlowRuleService.class, mockFlowService)
Ayaka Koshibec06c89b2015-02-10 19:25:41 -0800746 .add(CodecService.class, codecService)
747 .add(CoreService.class, mockCoreService);
Ray Milkey2b217142014-12-15 09:24:24 -0800748
749 BaseResource.setServiceDirectory(testDirectory);
750
Thomas Vachuska2048c1f2017-05-10 19:32:22 -0700751 MockIdGenerator.cleanBind();
Ray Milkey2b217142014-12-15 09:24:24 -0800752 }
753
Ray Milkeyed0b1662015-02-05 09:34:29 -0800754 /**
755 * Tears down and verifies test mocks and environment.
756 */
Ray Milkey2b217142014-12-15 09:24:24 -0800757 @After
Ray Milkeyed0b1662015-02-05 09:34:29 -0800758 public void tearDownTest() {
Thomas Vachuska2048c1f2017-05-10 19:32:22 -0700759 MockIdGenerator.unbind();
Ray Milkey2b217142014-12-15 09:24:24 -0800760 verify(mockIntentService);
Ray Milkey2b217142014-12-15 09:24:24 -0800761 }
762
763 /**
764 * Tests the result of the rest api GET when there are no intents.
765 */
766 @Test
767 public void testIntentsEmptyArray() {
768 replay(mockIntentService);
Jian Li9d616492016-03-09 10:52:49 -0800769 final WebTarget wt = target();
770 final String response = wt.path("intents").request().get(String.class);
Ray Milkey2b217142014-12-15 09:24:24 -0800771 assertThat(response, is("{\"intents\":[]}"));
772 }
773
774 /**
775 * Tests the result of the rest api GET when intents are defined.
776 */
777 @Test
778 public void testIntentsArray() {
779 replay(mockIntentService);
780
Ray Milkey43a28222015-02-23 13:57:58 -0800781 final Intent intent1 = new MockIntent(1L, Collections.emptyList());
Ray Milkey2b217142014-12-15 09:24:24 -0800782 final HashSet<NetworkResource> resources = new HashSet<>();
783 resources.add(new MockResource(1));
784 resources.add(new MockResource(2));
785 resources.add(new MockResource(3));
Ray Milkey43a28222015-02-23 13:57:58 -0800786 final Intent intent2 = new MockIntent(2L, resources);
Ray Milkey2b217142014-12-15 09:24:24 -0800787
788 intents.add(intent1);
789 intents.add(intent2);
Jian Li9d616492016-03-09 10:52:49 -0800790 final WebTarget wt = target();
791 final String response = wt.path("intents").request().get(String.class);
Ray Milkey2b217142014-12-15 09:24:24 -0800792 assertThat(response, containsString("{\"intents\":["));
793
Jian Li80cfe452016-01-14 16:04:58 -0800794 final JsonObject result = Json.parse(response).asObject();
Ray Milkey2b217142014-12-15 09:24:24 -0800795 assertThat(result, notNullValue());
796
797 assertThat(result.names(), hasSize(1));
798 assertThat(result.names().get(0), is("intents"));
799
800 final JsonArray jsonIntents = result.get("intents").asArray();
801 assertThat(jsonIntents, notNullValue());
802
803 assertThat(jsonIntents, hasIntent(intent1));
804 assertThat(jsonIntents, hasIntent(intent2));
805 }
806
807 /**
808 * Tests the result of a rest api GET for a single intent.
809 */
810 @Test
811 public void testIntentsSingle() {
812 final HashSet<NetworkResource> resources = new HashSet<>();
813 resources.add(new MockResource(1));
814 resources.add(new MockResource(2));
815 resources.add(new MockResource(3));
Ray Milkey43a28222015-02-23 13:57:58 -0800816 final Intent intent = new MockIntent(3L, resources);
Ray Milkey2b217142014-12-15 09:24:24 -0800817
818 intents.add(intent);
819
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800820 expect(mockIntentService.getIntent(Key.of(0, APP_ID)))
Ray Milkey2b217142014-12-15 09:24:24 -0800821 .andReturn(intent)
822 .anyTimes();
Ayaka Koshibec06c89b2015-02-10 19:25:41 -0800823 expect(mockIntentService.getIntent(Key.of("0", APP_ID)))
824 .andReturn(intent)
825 .anyTimes();
Ray Milkey05b169d2015-08-13 14:33:33 -0700826 expect(mockIntentService.getIntent(Key.of(0, APP_ID)))
827 .andReturn(intent)
828 .anyTimes();
829 expect(mockIntentService.getIntent(Key.of("0x0", APP_ID)))
830 .andReturn(null)
831 .anyTimes();
Ray Milkey2b217142014-12-15 09:24:24 -0800832 replay(mockIntentService);
Ray Milkeyf7cb4012015-07-20 13:01:07 -0700833 expect(mockCoreService.getAppId(APP_ID.name()))
Ayaka Koshibec06c89b2015-02-10 19:25:41 -0800834 .andReturn(APP_ID).anyTimes();
835 replay(mockCoreService);
Jian Li9d616492016-03-09 10:52:49 -0800836 final WebTarget wt = target();
Ray Milkey05b169d2015-08-13 14:33:33 -0700837
838 // Test get using key string
Jian Li9d616492016-03-09 10:52:49 -0800839 final String response = wt.path("intents/" + APP_ID.name()
840 + "/0").request().get(String.class);
Jian Li80cfe452016-01-14 16:04:58 -0800841 final JsonObject result = Json.parse(response).asObject();
Ray Milkey2b217142014-12-15 09:24:24 -0800842 assertThat(result, matchesIntent(intent));
Ray Milkey05b169d2015-08-13 14:33:33 -0700843
844 // Test get using numeric value
Jian Li9d616492016-03-09 10:52:49 -0800845 final String responseNumeric = wt.path("intents/" + APP_ID.name()
846 + "/0x0").request().get(String.class);
Jian Li80cfe452016-01-14 16:04:58 -0800847 final JsonObject resultNumeric = Json.parse(responseNumeric).asObject();
Ray Milkey05b169d2015-08-13 14:33:33 -0700848 assertThat(resultNumeric, matchesIntent(intent));
Ray Milkey2b217142014-12-15 09:24:24 -0800849 }
850
851 /**
Author Namee252a002016-09-26 22:42:24 +0530852 * Tests the result of a rest api GET for related flows for single intent.
853 */
854 @Test
855 public void testRelatedFlowsForIntents() {
856 List<FlowEntry> flowEntries = new ArrayList<>();
857 flowEntries.add(flow1);
858 flowEntries.add(flow2);
859 List<List<FlowEntry>> paths = new ArrayList<>();
860 paths.add(flowEntries);
861 List<FlowRule> flowRules = new ArrayList<>();
862 flowRules.add(flowRule1);
863 flowRules.add(flowRule2);
864 FlowRuleIntent flowRuleIntent = new FlowRuleIntent(
865 APP_ID,
Ray Milkey39f78b62018-01-05 15:17:37 -0800866 null,
Author Namee252a002016-09-26 22:42:24 +0530867 flowRules,
Ray Milkey39f78b62018-01-05 15:17:37 -0800868 new HashSet<NetworkResource>(),
869 PathIntent.ProtectionType.PRIMARY,
870 null);
Author Namee252a002016-09-26 22:42:24 +0530871 Intent intent = new MockIntent(3L);
872 installableIntents.add(flowRuleIntent);
873 intents.add(intent);
874
875 expect(mockIntentService.getIntent(Key.of(0, APP_ID)))
876 .andReturn(intent)
877 .anyTimes();
878 expect(mockIntentService.getIntent(Key.of("0", APP_ID)))
879 .andReturn(intent)
880 .anyTimes();
881 expect(mockIntentService.getIntent(Key.of(0, APP_ID)))
882 .andReturn(intent)
883 .anyTimes();
884 expect(mockIntentService.getIntent(Key.of("0x0", APP_ID)))
885 .andReturn(null)
886 .anyTimes();
887 expect(mockIntentService.getInstallableIntents(intent.key()))
888 .andReturn(installableIntents)
889 .anyTimes();
890 replay(mockIntentService);
891
892 expect(mockFlowService.getFlowEntries(deviceId1))
893 .andReturn(flowEntries).anyTimes();
894 replay(mockFlowService);
895
896 expect(mockCoreService.getAppId(APP_ID.name()))
897 .andReturn(APP_ID).anyTimes();
898 expect(mockCoreService.getAppId(APP_ID.id()))
899 .andReturn(APP_ID).anyTimes();
900 replay(mockCoreService);
901
902 final WebTarget wt = target();
903
904 // Test get using key string
905 final String response = wt.path("intents/relatedflows/" + APP_ID.name()
906 + "/0").request().get(String.class);
907 final JsonObject result = Json.parse(response).asObject();
908 assertThat(result, matchesRelatedFlowEntries(paths, APP_ID.name()));
909
910 // Test get using numeric value
911 final String responseNumeric = wt.path("intents/relatedflows/" + APP_ID.name()
912 + "/0x0").request().get(String.class);
913 final JsonObject resultNumeric = Json.parse(responseNumeric).asObject();
914 assertThat(resultNumeric, matchesRelatedFlowEntries(paths, APP_ID.name()));
915 }
916
917 /**
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +0200918 * Tests the result of a rest api GET for intent installables.
919 */
920 @Test
921 public void testIntentInstallables() {
922
923 Link link1 = DefaultLink.builder()
924 .type(Link.Type.DIRECT)
925 .providerId(ProviderId.NONE)
926 .src(connectPoint1)
927 .dst(connectPoint2)
928 .build();
929
930 Link link2 = DefaultLink.builder()
931 .type(Link.Type.DIRECT)
932 .providerId(ProviderId.NONE)
933 .src(connectPoint3)
934 .dst(connectPoint4)
935 .build();
936
937 Set<NetworkResource> resources = new HashSet<>();
938 resources.add(link1);
939 resources.add(link2);
940
941 FlowRuleIntent flowRuleIntent = new FlowRuleIntent(
942 APP_ID,
Ray Milkey39f78b62018-01-05 15:17:37 -0800943 null,
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +0200944 new ArrayList<>(),
Ray Milkey39f78b62018-01-05 15:17:37 -0800945 resources,
946 PathIntent.ProtectionType.PRIMARY,
947 null);
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +0200948
949 Intent intent = new MockIntent(MockIntent.nextId());
950 Long intentId = intent.id().id();
951 installableIntents.add(flowRuleIntent);
952 intents.add(intent);
953
954 expect(mockIntentService.getIntent(Key.of(intentId, APP_ID)))
955 .andReturn(intent)
956 .anyTimes();
957 expect(mockIntentService.getIntent(Key.of(intentId.toString(), APP_ID)))
958 .andReturn(intent)
959 .anyTimes();
960 expect(mockIntentService.getIntent(Key.of(intentId, APP_ID)))
961 .andReturn(intent)
962 .anyTimes();
963 expect(mockIntentService.getIntent(Key.of(Long.toHexString(intentId), APP_ID)))
964 .andReturn(null)
965 .anyTimes();
966 expect(mockIntentService.getInstallableIntents(intent.key()))
967 .andReturn(installableIntents)
968 .anyTimes();
969 replay(mockIntentService);
970
971 replay(mockFlowService);
972
973 expect(mockCoreService.getAppId(APP_ID.name()))
974 .andReturn(APP_ID).anyTimes();
975 expect(mockCoreService.getAppId(APP_ID.id()))
976 .andReturn(APP_ID).anyTimes();
977 replay(mockCoreService);
978
979 final WebTarget wt = target();
980
981 // Test get using key string
982 final String response = wt.path("intents/installables/" + APP_ID.name()
983 + "/" + intentId).request().get(String.class);
984 final JsonObject result = Json.parse(response).asObject();
985 assertThat(result.get(INSTALLABLES).asArray(), hasIntent(flowRuleIntent));
986
987 // Test get using numeric value
988 final String responseNumeric = wt.path("intents/installables/" + APP_ID.name()
989 + "/" + Long.toHexString(intentId)).request().get(String.class);
990 final JsonObject resultNumeric = Json.parse(responseNumeric).asObject();
991 assertThat(resultNumeric.get(INSTALLABLES).asArray(), hasIntent(flowRuleIntent));
992 }
993
994 /**
Ray Milkey2b217142014-12-15 09:24:24 -0800995 * Tests that a fetch of a non-existent intent object throws an exception.
996 */
997 @Test
998 public void testBadGet() {
999
Ray Milkeyf9af43c2015-02-09 16:45:48 -08001000 expect(mockIntentService.getIntent(Key.of(0, APP_ID)))
Ray Milkey2b217142014-12-15 09:24:24 -08001001 .andReturn(null)
1002 .anyTimes();
1003 replay(mockIntentService);
1004
Jian Li9d616492016-03-09 10:52:49 -08001005 WebTarget wt = target();
Ray Milkey2b217142014-12-15 09:24:24 -08001006 try {
Jian Li9d616492016-03-09 10:52:49 -08001007 wt.path("intents/0").request().get(String.class);
Ray Milkey2b217142014-12-15 09:24:24 -08001008 fail("Fetch of non-existent intent did not throw an exception");
Jian Li9d616492016-03-09 10:52:49 -08001009 } catch (NotFoundException ex) {
Ray Milkey2b217142014-12-15 09:24:24 -08001010 assertThat(ex.getMessage(),
Jian Li9d616492016-03-09 10:52:49 -08001011 containsString("HTTP 404 Not Found"));
Ray Milkey2b217142014-12-15 09:24:24 -08001012 }
1013 }
Ray Milkeyb82c42b2015-06-30 09:42:20 -07001014
1015 /**
1016 * Tests creating an intent with POST.
1017 */
1018 @Test
1019 public void testPost() {
Ray Milkeyf7cb4012015-07-20 13:01:07 -07001020 ApplicationId testId = new DefaultApplicationId(2, "myApp");
1021 expect(mockCoreService.getAppId("myApp"))
1022 .andReturn(testId);
Ray Milkeyb82c42b2015-06-30 09:42:20 -07001023 replay(mockCoreService);
1024
1025 mockIntentService.submit(anyObject());
1026 expectLastCall();
1027 replay(mockIntentService);
1028
1029 InputStream jsonStream = IntentsResourceTest.class
1030 .getResourceAsStream("post-intent.json");
Jian Li9d616492016-03-09 10:52:49 -08001031 WebTarget wt = target();
Ray Milkeyb82c42b2015-06-30 09:42:20 -07001032
Jian Li9d616492016-03-09 10:52:49 -08001033 Response response = wt.path("intents")
1034 .request(MediaType.APPLICATION_JSON_TYPE)
1035 .post(Entity.json(jsonStream));
Ray Milkeyb82c42b2015-06-30 09:42:20 -07001036 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
1037 String location = response.getLocation().getPath();
Ray Milkey8d076402015-08-31 15:43:18 -07001038 assertThat(location, Matchers.startsWith("/intents/myApp/"));
Ray Milkeyb82c42b2015-06-30 09:42:20 -07001039 }
Ray Milkey7b158512015-07-21 16:32:43 -07001040
1041 /**
Ray Milkey05b169d2015-08-13 14:33:33 -07001042 * Tests creating an intent with POST and illegal JSON.
1043 */
1044 @Test
1045 public void testBadPost() {
1046 replay(mockCoreService);
1047 replay(mockIntentService);
1048
1049 String json = "this is invalid!";
Jian Li9d616492016-03-09 10:52:49 -08001050 WebTarget wt = target();
Ray Milkey05b169d2015-08-13 14:33:33 -07001051
Jian Li9d616492016-03-09 10:52:49 -08001052 Response response = wt.path("intents")
1053 .request(MediaType.APPLICATION_JSON_TYPE)
1054 .post(Entity.json(json));
Ray Milkey05b169d2015-08-13 14:33:33 -07001055 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_BAD_REQUEST));
1056 }
1057
1058 /**
Ray Milkey7b158512015-07-21 16:32:43 -07001059 * Tests removing an intent with DELETE.
1060 */
1061 @Test
1062 public void testRemove() {
1063 final HashSet<NetworkResource> resources = new HashSet<>();
1064 resources.add(new MockResource(1));
1065 resources.add(new MockResource(2));
1066 resources.add(new MockResource(3));
1067 final Intent intent = new MockIntent(3L, resources);
1068 final ApplicationId appId = new DefaultApplicationId(2, "app");
1069 IntentService fakeManager = new FakeIntentManager();
1070
1071 expect(mockCoreService.getAppId("app"))
1072 .andReturn(appId).once();
1073 replay(mockCoreService);
1074
1075 mockIntentService.withdraw(anyObject());
1076 expectLastCall().andDelegateTo(fakeManager).once();
1077 expect(mockIntentService.getIntent(Key.of(2, appId)))
1078 .andReturn(intent)
1079 .once();
1080 expect(mockIntentService.getIntent(Key.of("0x2", appId)))
1081 .andReturn(null)
1082 .once();
1083
1084 mockIntentService.addListener(anyObject());
1085 expectLastCall().andDelegateTo(fakeManager).once();
1086 mockIntentService.removeListener(anyObject());
1087 expectLastCall().andDelegateTo(fakeManager).once();
1088
1089 replay(mockIntentService);
1090
Jian Li9d616492016-03-09 10:52:49 -08001091 WebTarget wt = target();
Ray Milkey7b158512015-07-21 16:32:43 -07001092
Jian Li9d616492016-03-09 10:52:49 -08001093 Response response = wt.path("intents/app/0x2")
Ray Milkey7c251822016-04-06 17:38:25 -07001094 .request(MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN)
Jian Li9d616492016-03-09 10:52:49 -08001095 .delete();
Ray Milkey7b158512015-07-21 16:32:43 -07001096 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NO_CONTENT));
1097 }
Ray Milkey05b169d2015-08-13 14:33:33 -07001098
1099 /**
1100 * Tests removal of a non existent intent with DELETE.
1101 */
1102 @Test
1103 public void testBadRemove() {
1104 final ApplicationId appId = new DefaultApplicationId(2, "app");
1105
1106 expect(mockCoreService.getAppId("app"))
1107 .andReturn(appId).once();
1108 replay(mockCoreService);
1109
1110 expect(mockIntentService.getIntent(Key.of(2, appId)))
1111 .andReturn(null)
1112 .once();
1113 expect(mockIntentService.getIntent(Key.of("0x2", appId)))
1114 .andReturn(null)
1115 .once();
1116
1117 replay(mockIntentService);
1118
Jian Li9d616492016-03-09 10:52:49 -08001119 WebTarget wt = target();
Ray Milkey05b169d2015-08-13 14:33:33 -07001120
Jian Li9d616492016-03-09 10:52:49 -08001121 Response response = wt.path("intents/app/0x2")
Ray Milkey7c251822016-04-06 17:38:25 -07001122 .request(MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN)
Jian Li9d616492016-03-09 10:52:49 -08001123 .delete();
Ray Milkey05b169d2015-08-13 14:33:33 -07001124 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NO_CONTENT));
1125 }
1126
dvaddire95c84ed2017-06-14 15:42:24 +05301127 @Test
1128 public void testIntentsMiniSummary() {
1129 final Intent intent1 = new MockIntent(1L, Collections.emptyList());
1130 final HashSet<NetworkResource> resources = new HashSet<>();
1131 resources.add(new MockResource(1));
1132 resources.add(new MockResource(2));
1133 resources.add(new MockResource(3));
1134 final Intent intent2 = new MockIntent(2L, resources);
1135 intents.add(intent1);
1136 intents.add(intent2);
1137 final WebTarget wt = target();
1138 replay(mockIntentService);
1139 final String response = wt.path("intents/minisummary").request().get(String.class);
1140 assertThat(response, containsString("{\"All\":{"));
1141 final JsonObject result = Json.parse(response).asObject();
1142 assertThat(result, notNullValue());
1143 assertThat(result.names(), hasSize(2));
1144 assertThat(result.names().get(0), containsString("All"));
1145 JsonObject jsonIntents = (JsonObject) result.get("All");
1146 assertThat(jsonIntents, notNullValue());
1147 assertThat(jsonIntents.get("total").toString(), containsString("2"));
1148 jsonIntents = (JsonObject) result.get("Mock");
1149 assertThat(jsonIntents, notNullValue());
1150 assertThat(jsonIntents.get("installed").toString(), containsString("2"));
1151 }
Ray Milkey2b217142014-12-15 09:24:24 -08001152}
dvaddire95c84ed2017-06-14 15:42:24 +05301153