blob: 318f90d36ceee77ac11608f3158c94231e328019 [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.onosproject.codec.CodecService;
33import org.onosproject.codec.impl.CodecManager;
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +020034import org.onosproject.codec.impl.MockCodecContext;
Ray Milkey2b217142014-12-15 09:24:24 -080035import org.onosproject.core.ApplicationId;
Ayaka Koshibec06c89b2015-02-10 19:25:41 -080036import org.onosproject.core.CoreService;
Ray Milkey2b217142014-12-15 09:24:24 -080037import org.onosproject.core.DefaultApplicationId;
Author Namee252a002016-09-26 22:42:24 +053038import org.onosproject.core.GroupId;
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +020039import org.onosproject.net.ConnectPoint;
40import org.onosproject.net.DefaultLink;
Author Namee252a002016-09-26 22:42:24 +053041import org.onosproject.net.DeviceId;
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +020042import org.onosproject.net.Link;
Ray Milkey2b217142014-12-15 09:24:24 -080043import org.onosproject.net.NetworkResource;
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +020044import org.onosproject.net.PortNumber;
Author Namee252a002016-09-26 22:42:24 +053045import org.onosproject.net.flow.DefaultTrafficSelector;
46import org.onosproject.net.flow.DefaultTrafficTreatment;
47import org.onosproject.net.flow.FlowEntry;
Ray Milkey634eb172017-04-05 14:48:50 -070048import org.onosproject.net.flow.FlowEntryAdapter;
Author Namee252a002016-09-26 22:42:24 +053049import org.onosproject.net.flow.FlowId;
50import org.onosproject.net.flow.FlowRule;
Author Namee252a002016-09-26 22:42:24 +053051import org.onosproject.net.flow.FlowRuleService;
Carmelo Cascone41605742017-06-19 15:46:44 +090052import org.onosproject.net.flow.TableId;
Author Namee252a002016-09-26 22:42:24 +053053import org.onosproject.net.flow.TrafficSelector;
54import org.onosproject.net.flow.TrafficTreatment;
55import org.onosproject.net.flow.criteria.Criterion;
56import org.onosproject.net.flow.instructions.Instruction;
Ray Milkey7b158512015-07-21 16:32:43 -070057import org.onosproject.net.intent.FakeIntentManager;
Author Namee252a002016-09-26 22:42:24 +053058import org.onosproject.net.intent.FlowRuleIntent;
Ray Milkey2b217142014-12-15 09:24:24 -080059import org.onosproject.net.intent.Intent;
Ray Milkey2b217142014-12-15 09:24:24 -080060import org.onosproject.net.intent.IntentService;
Ray Milkey1534f8d2015-05-13 15:42:50 -070061import org.onosproject.net.intent.IntentState;
Ray Milkeyf9af43c2015-02-09 16:45:48 -080062import org.onosproject.net.intent.Key;
Thomas Vachuska2048c1f2017-05-10 19:32:22 -070063import org.onosproject.net.intent.MockIdGenerator;
Ray Milkey39f78b62018-01-05 15:17:37 -080064import org.onosproject.net.intent.PathIntent;
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +020065import org.onosproject.net.provider.ProviderId;
Ray Milkey2b217142014-12-15 09:24:24 -080066
dvaddire95c84ed2017-06-14 15:42:24 +053067
Author Namee252a002016-09-26 22:42:24 +053068import javax.ws.rs.NotFoundException;
69import javax.ws.rs.client.Entity;
70import javax.ws.rs.client.WebTarget;
71import javax.ws.rs.core.MediaType;
72import javax.ws.rs.core.Response;
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +020073import java.io.IOException;
Author Namee252a002016-09-26 22:42:24 +053074import java.io.InputStream;
75import java.net.HttpURLConnection;
76import java.util.ArrayList;
77import java.util.Collections;
78import java.util.HashSet;
79import java.util.List;
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +020080import java.util.Set;
Author Namee252a002016-09-26 22:42:24 +053081import java.util.concurrent.TimeUnit;
Ray Milkey2b217142014-12-15 09:24:24 -080082
Author Namee252a002016-09-26 22:42:24 +053083import static java.util.concurrent.TimeUnit.SECONDS;
84import static org.easymock.EasyMock.*;
85import static org.hamcrest.Matchers.*;
Ray Milkey2b217142014-12-15 09:24:24 -080086import static org.junit.Assert.assertThat;
87import static org.junit.Assert.fail;
Ray Milkey43a28222015-02-23 13:57:58 -080088import static org.onosproject.net.intent.IntentTestsMocks.MockIntent;
Ray Milkey2b217142014-12-15 09:24:24 -080089
90/**
91 * Unit tests for Intents REST APIs.
92 */
Ray Milkey9c3d3362015-01-28 10:39:56 -080093public class IntentsResourceTest extends ResourceTest {
Author Namee252a002016-09-26 22:42:24 +053094
95
96 private static final String APPID = "appId";
97 private static final String CRITERIA = "criteria";
98 private static final String DEVICE_ID = "deviceId";
99 private static final String ID = "id";
100 private static final String INSTRUCTIONS = "instructions";
101 private static final String PATHS = "paths";
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +0200102 private static final String INSTALLABLES = "installables";
103 private static final String RESOURCES = "resources";
104 private static final String DEVICE = "device";
105 private static final String PORT = "port";
106 private static final String SRC = "src";
107 private static final String DST = "dst";
Author Namee252a002016-09-26 22:42:24 +0530108 private static final String SELECTOR = "selector";
109 private static final String SPACE = " ";
110 private static final String TREATMENT = "treatment";
111 private static final String TYPE = "type";
112
Ray Milkey2b217142014-12-15 09:24:24 -0800113 final IntentService mockIntentService = createMock(IntentService.class);
Ayaka Koshibec06c89b2015-02-10 19:25:41 -0800114 final CoreService mockCoreService = createMock(CoreService.class);
Author Namee252a002016-09-26 22:42:24 +0530115 final FlowRuleService mockFlowService = createMock(FlowRuleService.class);
Ray Milkey2b217142014-12-15 09:24:24 -0800116 final HashSet<Intent> intents = new HashSet<>();
Author Namee252a002016-09-26 22:42:24 +0530117 final List<org.onosproject.net.intent.Intent> installableIntents = new ArrayList<>();
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800118 private static final ApplicationId APP_ID = new DefaultApplicationId(1, "test");
Ray Milkey2b217142014-12-15 09:24:24 -0800119
Author Namee252a002016-09-26 22:42:24 +0530120 final DeviceId deviceId1 = DeviceId.deviceId("1");
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +0200121 final DeviceId deviceId2 = DeviceId.deviceId("2");
122 final DeviceId deviceId3 = DeviceId.deviceId("3");
123
124 final ConnectPoint connectPoint1 = new ConnectPoint(deviceId1, PortNumber.portNumber(1L));
125 final ConnectPoint connectPoint2 = new ConnectPoint(deviceId2, PortNumber.portNumber(1L));
126 final ConnectPoint connectPoint3 = new ConnectPoint(deviceId2, PortNumber.portNumber(2L));
127 final ConnectPoint connectPoint4 = new ConnectPoint(deviceId3, PortNumber.portNumber(1L));
Author Namee252a002016-09-26 22:42:24 +0530128
129 final TrafficTreatment treatment1 = DefaultTrafficTreatment.builder()
130 .setEthDst(MacAddress.BROADCAST)
131 .build();
132 final TrafficTreatment treatment2 = DefaultTrafficTreatment.builder()
133 .setEthDst(MacAddress.IPV4_MULTICAST)
134 .build();
135
136 final TrafficSelector selector1 = DefaultTrafficSelector.builder()
137 .matchEthType((short) 3)
138 .matchIPProtocol((byte) 9)
139 .build();
140 final TrafficSelector selector2 = DefaultTrafficSelector.builder()
141 .matchEthType((short) 4)
142 .matchIPProtocol((byte) 10)
143 .build();
144
145 final MockFlowEntry flow1 = new MockFlowEntry(deviceId1, 1, treatment1, selector1);
146 final MockFlowEntry flow2 = new MockFlowEntry(deviceId1, 2, treatment2, selector2);
147
148 final MockFlowRule flowRule1 = new MockFlowRule(deviceId1, 1, treatment1, selector1);
149 final MockFlowRule flowRule2 = new MockFlowRule(deviceId1, 2, treatment2, selector2);
150
Ray Milkey2b217142014-12-15 09:24:24 -0800151 private class MockResource implements NetworkResource {
152 int id;
153
154 MockResource(int id) {
155 this.id = id;
156 }
157
Ayaka Koshibec06c89b2015-02-10 19:25:41 -0800158 @Override
Ray Milkey2b217142014-12-15 09:24:24 -0800159 public String toString() {
160 return "Resource " + Integer.toString(id);
161 }
162 }
163
Ray Milkey2b217142014-12-15 09:24:24 -0800164 /**
Author Namee252a002016-09-26 22:42:24 +0530165 * Mock class for a flow entry.
166 */
Ray Milkey634eb172017-04-05 14:48:50 -0700167 private static class MockFlowEntry extends FlowEntryAdapter {
Author Namee252a002016-09-26 22:42:24 +0530168 final DeviceId deviceId;
169 final long baseValue;
170 TrafficTreatment treatment;
171 TrafficSelector selector;
172
173 public MockFlowEntry(DeviceId deviceId, long id,
174 TrafficTreatment treatment,
175 TrafficSelector selector) {
176 this.deviceId = deviceId;
177 this.baseValue = id * 100;
178 this.treatment = treatment;
179 this.selector = selector;
180 }
181
182 @Override
Author Namee252a002016-09-26 22:42:24 +0530183 public long life() {
184 return life(SECONDS);
185 }
186
187 @Override
kalagesa42019542017-03-14 18:00:47 +0530188 public FlowLiveType liveType() {
189 return FlowLiveType.IMMEDIATE;
190 }
191
192 @Override
Author Namee252a002016-09-26 22:42:24 +0530193 public long life(TimeUnit timeUnit) {
194 return SECONDS.convert(baseValue + 11, timeUnit);
195 }
196
197 @Override
198 public long packets() {
199 return baseValue + 22;
200 }
201
202 @Override
203 public long bytes() {
204 return baseValue + 33;
205 }
206
207 @Override
208 public long lastSeen() {
209 return baseValue + 44;
210 }
211
212 @Override
Author Namee252a002016-09-26 22:42:24 +0530213 public FlowId id() {
214 final long id = baseValue + 55;
215 return FlowId.valueOf(id);
216 }
217
218 @Override
219 public GroupId groupId() {
Yi Tsengfa394de2017-02-01 11:26:40 -0800220 return new GroupId(3);
Author Namee252a002016-09-26 22:42:24 +0530221 }
222
223 @Override
224 public short appId() {
225 return 1;
226 }
227
228 @Override
229 public int priority() {
230 return (int) (baseValue + 66);
231 }
232
233 @Override
234 public DeviceId deviceId() {
235 return deviceId;
236 }
237
238 @Override
239 public TrafficSelector selector() {
240 return selector;
241 }
242
243 @Override
244 public TrafficTreatment treatment() {
245 return treatment;
246 }
247
248 @Override
249 public int timeout() {
250 return (int) (baseValue + 77);
251 }
252
Author Namee252a002016-09-26 22:42:24 +0530253
254 @Override
255 public boolean exactMatch(FlowRule rule) {
256 return this.appId() == rule.appId() &&
257 this.deviceId().equals(rule.deviceId()) &&
258 this.id().equals(rule.id()) &&
259 this.treatment.equals(rule.treatment()) &&
260 this.selector().equals(rule.selector());
261 }
262
263 @Override
Author Namee252a002016-09-26 22:42:24 +0530264 public String toString() {
265 return id().id().toString();
266 }
267 }
268
269 /**
270 * Mock class for a flow rule.
271 */
272 private static class MockFlowRule implements FlowRule {
273
274 final DeviceId deviceId;
275 final long baseValue;
276 TrafficTreatment treatment;
277 TrafficSelector selector;
278
279 public MockFlowRule(DeviceId deviceId,
280 long id,
281 TrafficTreatment treatment,
282 TrafficSelector selector) {
283 this.deviceId = deviceId;
284 this.baseValue = id * 100;
285 this.treatment = treatment;
286 this.selector = selector;
287 }
288
289 @Override
290 public FlowId id() {
291 long id = baseValue + 55;
292 return FlowId.valueOf(id);
293 }
294
295 @Override
296 public short appId() {
297 return 1;
298 }
299
300 @Override
301 public GroupId groupId() {
Yi Tsengfa394de2017-02-01 11:26:40 -0800302 return new GroupId(3);
Author Namee252a002016-09-26 22:42:24 +0530303 }
304
305 @Override
306 public int priority() {
307 return 0;
308 }
309
310 @Override
311 public DeviceId deviceId() {
312 return deviceId;
313 }
314
315 @Override
316 public TrafficSelector selector() {
317 return selector;
318 }
319
320 @Override
321 public TrafficTreatment treatment() {
322 return treatment;
323 }
324
325 @Override
326 public int timeout() {
327 return (int) (baseValue + 77);
328 }
329
330 @Override
331 public int hardTimeout() {
332 return 0;
333 }
334
335 @Override
336 public FlowRemoveReason reason() {
337 return FlowRemoveReason.NO_REASON;
338 }
339
340 @Override
341 public boolean isPermanent() {
342 return false;
343 }
344
345 @Override
346 public int tableId() {
347 return 0;
348 }
349
350 @Override
Carmelo Cascone41605742017-06-19 15:46:44 +0900351 public TableId table() {
352 return DEFAULT_TABLE;
353 }
354
355 @Override
Author Namee252a002016-09-26 22:42:24 +0530356 public boolean exactMatch(FlowRule rule) {
357 return false;
358 }
Author Namee252a002016-09-26 22:42:24 +0530359 }
360
361 /**
Ray Milkey2b217142014-12-15 09:24:24 -0800362 * Hamcrest matcher to check that an intent representation in JSON matches
363 * the actual intent.
364 */
365 public static class IntentJsonMatcher extends TypeSafeMatcher<JsonObject> {
366 private final Intent intent;
367 private String reason = "";
368
369 public IntentJsonMatcher(Intent intentValue) {
370 intent = intentValue;
371 }
372
373 @Override
374 public boolean matchesSafely(JsonObject jsonIntent) {
375 // check id
376 final String jsonId = jsonIntent.get("id").asString();
377 if (!jsonId.equals(intent.id().toString())) {
378 reason = "id " + intent.id().toString();
379 return false;
380 }
381
382 // check application id
Ray Milkeyf7cb4012015-07-20 13:01:07 -0700383
Ray Milkey2b217142014-12-15 09:24:24 -0800384 final String jsonAppId = jsonIntent.get("appId").asString();
Ray Milkeyf7cb4012015-07-20 13:01:07 -0700385 final String appId = intent.appId().name();
386 if (!jsonAppId.equals(appId)) {
387 reason = "appId was " + jsonAppId;
Ray Milkey2b217142014-12-15 09:24:24 -0800388 return false;
389 }
390
391 // check intent type
392 final String jsonType = jsonIntent.get("type").asString();
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +0200393 if (!intent.getClass().getSimpleName().equals(jsonType)) {
Ray Milkey2b217142014-12-15 09:24:24 -0800394 reason = "type MockIntent";
395 return false;
396 }
397
Ray Milkey1534f8d2015-05-13 15:42:50 -0700398 // check state field
399 final String jsonState = jsonIntent.get("state").asString();
Jon Halla3fcf672017-03-28 16:53:22 -0700400 if (!"INSTALLED".equals(jsonState)) {
Ray Milkey1534f8d2015-05-13 15:42:50 -0700401 reason = "state INSTALLED";
402 return false;
403 }
404
Ray Milkey2b217142014-12-15 09:24:24 -0800405 // check resources array
406 final JsonArray jsonResources = jsonIntent.get("resources").asArray();
407 if (intent.resources() != null) {
408 if (intent.resources().size() != jsonResources.size()) {
409 reason = "resources array size of " + Integer.toString(intent.resources().size());
410 return false;
411 }
412 for (final NetworkResource resource : intent.resources()) {
413 boolean resourceFound = false;
414 final String resourceString = resource.toString();
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +0200415
416 if (resource instanceof Link) {
417 final Link resourceLink = (Link) resource;
418 MockCodecContext codecContext = new MockCodecContext();
419
420 for (int resourceIndex = 0; resourceIndex < jsonResources.size(); resourceIndex++) {
421 final ObjectNode value;
422 try {
423 value = (ObjectNode) codecContext.mapper()
424 .readTree(jsonResources.get(resourceIndex).toString());
425 } catch (IOException e) {
426 reason = "bad json";
427 return false;
428 }
429 final Link link = codecContext.codec(Link.class).decode(value, codecContext);
430 if (resourceLink.equals(link)) {
431 resourceFound = true;
432 }
433 }
434 } else {
435
436 for (int resourceIndex = 0; resourceIndex < jsonResources.size(); resourceIndex++) {
437 final JsonValue value = jsonResources.get(resourceIndex);
438 if (value.asString().equals(resourceString)) {
439 resourceFound = true;
440 }
Ray Milkey2b217142014-12-15 09:24:24 -0800441 }
442 }
443 if (!resourceFound) {
444 reason = "resource " + resourceString;
445 return false;
446 }
447 }
448 } else if (jsonResources.size() != 0) {
449 reason = "resources array empty";
450 return false;
451 }
452 return true;
453 }
454
455 @Override
456 public void describeTo(Description description) {
457 description.appendText(reason);
458 }
459 }
460
461 /**
462 * Factory to allocate an intent matcher.
463 *
464 * @param intent intent object we are looking for
465 * @return matcher
466 */
467 private static IntentJsonMatcher matchesIntent(Intent intent) {
468 return new IntentJsonMatcher(intent);
469 }
470
471 /**
Author Namee252a002016-09-26 22:42:24 +0530472 * Factory to allocate an IntentRelatedFlows matcher.
473 *
dvaddire95c84ed2017-06-14 15:42:24 +0530474 * @param pathEntries list of path conatining flow entries of a particular intent
Author Namee252a002016-09-26 22:42:24 +0530475 * @param expectedAppId expected app id we are looking for
476 * @return matcher
477 */
478 private static IntentStatsJsonMatcher matchesRelatedFlowEntries(
479 List<List<FlowEntry>> pathEntries,
480 final String expectedAppId) {
481 return new IntentStatsJsonMatcher(pathEntries, expectedAppId);
482 }
483
484 /**
485 * Hamcrest matcher to check that an list of flowEntries in JSON matches
486 * the actual list of flow entries.
487 */
488 public static class IntentStatsJsonMatcher extends
489 TypeSafeMatcher<JsonObject> {
490
491 private final List<List<FlowEntry>> pathEntries;
492 private final String expectedAppId;
493 private String reason = "";
494
495 public IntentStatsJsonMatcher(
496 final List<List<FlowEntry>> pathEntries,
497 final String expectedAppId) {
498 this.pathEntries = pathEntries;
499 this.expectedAppId = expectedAppId;
500 }
501
502 @Override
503 public boolean matchesSafely(JsonObject jsonIntent) {
504 int jsonPathIndex = 0;
505 JsonArray jsonPaths = jsonIntent.get(PATHS).asArray();
506
507 if (pathEntries != null) {
508
rohitsharanfd747602017-01-23 21:57:28 +0530509 if (pathEntries.size() == 0) {
510 reason = "pathEntries array empty";
511 return false;
512 }
513
Author Namee252a002016-09-26 22:42:24 +0530514 if (pathEntries.size() != jsonPaths.size()) {
515 reason = "path entries array size of " +
516 Integer.toString(pathEntries.size());
517 return false;
518 }
519
520 for (List<FlowEntry> flowEntries : pathEntries) {
521 JsonArray jsonFlowEntries = jsonPaths.get(
522 jsonPathIndex++).asArray();
523
524 if (flowEntries.size() != jsonFlowEntries.size()) {
525 reason = "flow entries array size of " +
526 Integer.toString(pathEntries.size());
527
528 return false;
529 }
530
531 int jsonFlowEntryIndex = 0;
532 for (FlowEntry flow : flowEntries) {
533
534 JsonObject jsonFlow = jsonFlowEntries.get(
535 jsonFlowEntryIndex++).asObject();
536
537 String jsonId = jsonFlow.get(ID).asString();
538 String flowId = Long.toString(flow.id().value());
539 if (!jsonId.equals(flowId)) {
540 reason = ID + SPACE + flow.id();
541 return false;
542 }
543
544 // check application id
545 String jsonAppId = jsonFlow.get(APPID).asString();
546 if (!jsonAppId.equals(expectedAppId)) {
547 reason = APPID + SPACE + Short.toString(flow.appId());
548 return false;
549 }
550
551 // check device id
552 String jsonDeviceId =
553 jsonFlow.get(DEVICE_ID).asString();
554
555 if (!jsonDeviceId.equals(flow.deviceId().toString())) {
556 reason = DEVICE_ID + SPACE + flow.deviceId();
557 return false;
558 }
559
560 if (!checkFlowTreatment(flow, jsonFlow)) {
561 return false;
562 }
563
564 if (!checkFlowSelector(flow, jsonFlow)) {
565 return false;
566 }
567
568 }
569
570 }
rohitsharanfd747602017-01-23 21:57:28 +0530571 } else {
Author Namee252a002016-09-26 22:42:24 +0530572 reason = "pathEntries array empty";
573 return false;
574 }
575
576 return true;
577 }
578
579 // check treatment and instructions array.
580 private boolean checkFlowTreatment(FlowEntry flow, JsonObject jsonFlow) {
581
582 if (flow.treatment() != null) {
583 JsonObject jsonTreatment =
584 jsonFlow.get(TREATMENT).asObject();
585 JsonArray jsonInstructions =
586 jsonTreatment.get(INSTRUCTIONS).asArray();
587
588 if (flow.treatment().immediate().size() !=
589 jsonInstructions.size()) {
590 reason = "instructions array size of " +
591 flow.treatment().immediate().size();
592
593 return false;
594 }
595 for (Instruction instruction :
596 flow.treatment().immediate()) {
597 boolean instructionFound = false;
598 for (int instructionIndex = 0;
599 instructionIndex < jsonInstructions.size();
600 instructionIndex++) {
601 String jsonType =
602 jsonInstructions.get(instructionIndex)
603 .asObject().get(TYPE).asString();
604
605 String instructionType =
606 instruction.type().name();
607
608 if (jsonType.equals(instructionType)) {
609 instructionFound = true;
610 }
611 }
612 if (!instructionFound) {
613 reason = INSTRUCTIONS + SPACE + instruction;
614 return false;
615 }
616 }
617 }
618 return true;
619 }
620
621 // check selector and criteria array.
622 private boolean checkFlowSelector(FlowEntry flow, JsonObject jsonFlow) {
623
624 if (flow.selector() != null) {
625 JsonObject jsonTreatment =
626 jsonFlow.get(SELECTOR).asObject();
627
628 JsonArray jsonCriteria =
629 jsonTreatment.get(CRITERIA).asArray();
630
631 if (flow.selector().criteria().size() != jsonCriteria.size()) {
632 reason = CRITERIA + " array size of " +
633 Integer.toString(flow.selector().criteria().size());
634 return false;
635 }
636 for (Criterion criterion : flow.selector().criteria()) {
637 boolean criterionFound = false;
638
639 for (int criterionIndex = 0;
640 criterionIndex < jsonCriteria.size();
641 criterionIndex++) {
642 String jsonType =
643 jsonCriteria.get(criterionIndex)
644 .asObject().get(TYPE).asString();
645 String criterionType = criterion.type().name();
646 if (jsonType.equals(criterionType)) {
647 criterionFound = true;
648 }
649 }
650 if (!criterionFound) {
651 reason = "criterion " + criterion;
652 return false;
653 }
654 }
655 }
656 return true;
657 }
658
659 @Override
660 public void describeTo(Description description) {
661 description.appendText(reason);
662 }
663 }
664
665 /**
Ray Milkey2b217142014-12-15 09:24:24 -0800666 * Hamcrest matcher to check that an intent is represented properly in a JSON
667 * array of intents.
668 */
669 public static class IntentJsonArrayMatcher extends TypeSafeMatcher<JsonArray> {
670 private final Intent intent;
671 private String reason = "";
672
673 public IntentJsonArrayMatcher(Intent intentValue) {
674 intent = intentValue;
675 }
676
677 @Override
678 public boolean matchesSafely(JsonArray json) {
679 boolean intentFound = false;
Antonio Marsico4f68ec92017-03-09 11:16:32 +0100680 final int expectedAttributes = 6;
Ray Milkey2b217142014-12-15 09:24:24 -0800681 for (int jsonIntentIndex = 0; jsonIntentIndex < json.size();
682 jsonIntentIndex++) {
683
684 final JsonObject jsonIntent = json.get(jsonIntentIndex).asObject();
685
686 if (jsonIntent.names().size() != expectedAttributes) {
687 reason = "Found an intent with the wrong number of attributes";
688 return false;
689 }
690
691 final String jsonIntentId = jsonIntent.get("id").asString();
692 if (jsonIntentId.equals(intent.id().toString())) {
693 intentFound = true;
694
695 // We found the correct intent, check attribute values
696 assertThat(jsonIntent, matchesIntent(intent));
697 }
698 }
699 if (!intentFound) {
700 reason = "Intent with id " + intent.id().toString() + " not found";
701 return false;
702 } else {
703 return true;
704 }
705 }
706
707 @Override
708 public void describeTo(Description description) {
709 description.appendText(reason);
710 }
711 }
712
713 /**
714 * Factory to allocate an intent array matcher.
715 *
716 * @param intent intent object we are looking for
717 * @return matcher
718 */
719 private static IntentJsonArrayMatcher hasIntent(Intent intent) {
720 return new IntentJsonArrayMatcher(intent);
721 }
Ray Milkey4f5de002014-12-17 19:26:11 -0800722
Ray Milkeyed0b1662015-02-05 09:34:29 -0800723 /**
724 * Initializes test mocks and environment.
725 */
Ray Milkey2b217142014-12-15 09:24:24 -0800726 @Before
Ray Milkeyed0b1662015-02-05 09:34:29 -0800727 public void setUpTest() {
Ray Milkey2b217142014-12-15 09:24:24 -0800728 expect(mockIntentService.getIntents()).andReturn(intents).anyTimes();
Ray Milkey1534f8d2015-05-13 15:42:50 -0700729 expect(mockIntentService.getIntentState(anyObject()))
730 .andReturn(IntentState.INSTALLED)
731 .anyTimes();
Ray Milkey2b217142014-12-15 09:24:24 -0800732 // Register the services needed for the test
dvaddire95c84ed2017-06-14 15:42:24 +0530733 final CodecManager codecService = new CodecManager();
Ray Milkey2b217142014-12-15 09:24:24 -0800734 codecService.activate();
735 ServiceDirectory testDirectory =
736 new TestServiceDirectory()
737 .add(IntentService.class, mockIntentService)
Author Namee252a002016-09-26 22:42:24 +0530738 .add(FlowRuleService.class, mockFlowService)
Ayaka Koshibec06c89b2015-02-10 19:25:41 -0800739 .add(CodecService.class, codecService)
740 .add(CoreService.class, mockCoreService);
Ray Milkey2b217142014-12-15 09:24:24 -0800741
Ray Milkey094a1352018-01-22 14:03:54 -0800742 setServiceDirectory(testDirectory);
Ray Milkey2b217142014-12-15 09:24:24 -0800743
Thomas Vachuska2048c1f2017-05-10 19:32:22 -0700744 MockIdGenerator.cleanBind();
Ray Milkey2b217142014-12-15 09:24:24 -0800745 }
746
Ray Milkeyed0b1662015-02-05 09:34:29 -0800747 /**
748 * Tears down and verifies test mocks and environment.
749 */
Ray Milkey2b217142014-12-15 09:24:24 -0800750 @After
Ray Milkeyed0b1662015-02-05 09:34:29 -0800751 public void tearDownTest() {
Thomas Vachuska2048c1f2017-05-10 19:32:22 -0700752 MockIdGenerator.unbind();
Ray Milkey2b217142014-12-15 09:24:24 -0800753 verify(mockIntentService);
Ray Milkey2b217142014-12-15 09:24:24 -0800754 }
755
756 /**
757 * Tests the result of the rest api GET when there are no intents.
758 */
759 @Test
760 public void testIntentsEmptyArray() {
761 replay(mockIntentService);
Jian Li9d616492016-03-09 10:52:49 -0800762 final WebTarget wt = target();
763 final String response = wt.path("intents").request().get(String.class);
Ray Milkey2b217142014-12-15 09:24:24 -0800764 assertThat(response, is("{\"intents\":[]}"));
765 }
766
767 /**
768 * Tests the result of the rest api GET when intents are defined.
769 */
770 @Test
771 public void testIntentsArray() {
772 replay(mockIntentService);
773
Ray Milkey43a28222015-02-23 13:57:58 -0800774 final Intent intent1 = new MockIntent(1L, Collections.emptyList());
Ray Milkey2b217142014-12-15 09:24:24 -0800775 final HashSet<NetworkResource> resources = new HashSet<>();
776 resources.add(new MockResource(1));
777 resources.add(new MockResource(2));
778 resources.add(new MockResource(3));
Ray Milkey43a28222015-02-23 13:57:58 -0800779 final Intent intent2 = new MockIntent(2L, resources);
Ray Milkey2b217142014-12-15 09:24:24 -0800780
781 intents.add(intent1);
782 intents.add(intent2);
Jian Li9d616492016-03-09 10:52:49 -0800783 final WebTarget wt = target();
784 final String response = wt.path("intents").request().get(String.class);
Ray Milkey2b217142014-12-15 09:24:24 -0800785 assertThat(response, containsString("{\"intents\":["));
786
Jian Li80cfe452016-01-14 16:04:58 -0800787 final JsonObject result = Json.parse(response).asObject();
Ray Milkey2b217142014-12-15 09:24:24 -0800788 assertThat(result, notNullValue());
789
790 assertThat(result.names(), hasSize(1));
791 assertThat(result.names().get(0), is("intents"));
792
793 final JsonArray jsonIntents = result.get("intents").asArray();
794 assertThat(jsonIntents, notNullValue());
795
796 assertThat(jsonIntents, hasIntent(intent1));
797 assertThat(jsonIntents, hasIntent(intent2));
798 }
799
800 /**
801 * Tests the result of a rest api GET for a single intent.
802 */
803 @Test
804 public void testIntentsSingle() {
805 final HashSet<NetworkResource> resources = new HashSet<>();
806 resources.add(new MockResource(1));
807 resources.add(new MockResource(2));
808 resources.add(new MockResource(3));
Ray Milkey43a28222015-02-23 13:57:58 -0800809 final Intent intent = new MockIntent(3L, resources);
Ray Milkey2b217142014-12-15 09:24:24 -0800810
811 intents.add(intent);
812
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800813 expect(mockIntentService.getIntent(Key.of(0, APP_ID)))
Ray Milkey2b217142014-12-15 09:24:24 -0800814 .andReturn(intent)
815 .anyTimes();
Ayaka Koshibec06c89b2015-02-10 19:25:41 -0800816 expect(mockIntentService.getIntent(Key.of("0", APP_ID)))
817 .andReturn(intent)
818 .anyTimes();
Ray Milkey05b169d2015-08-13 14:33:33 -0700819 expect(mockIntentService.getIntent(Key.of(0, APP_ID)))
820 .andReturn(intent)
821 .anyTimes();
822 expect(mockIntentService.getIntent(Key.of("0x0", APP_ID)))
823 .andReturn(null)
824 .anyTimes();
Ray Milkey2b217142014-12-15 09:24:24 -0800825 replay(mockIntentService);
Ray Milkeyf7cb4012015-07-20 13:01:07 -0700826 expect(mockCoreService.getAppId(APP_ID.name()))
Ayaka Koshibec06c89b2015-02-10 19:25:41 -0800827 .andReturn(APP_ID).anyTimes();
828 replay(mockCoreService);
Jian Li9d616492016-03-09 10:52:49 -0800829 final WebTarget wt = target();
Ray Milkey05b169d2015-08-13 14:33:33 -0700830
831 // Test get using key string
Jian Li9d616492016-03-09 10:52:49 -0800832 final String response = wt.path("intents/" + APP_ID.name()
833 + "/0").request().get(String.class);
Jian Li80cfe452016-01-14 16:04:58 -0800834 final JsonObject result = Json.parse(response).asObject();
Ray Milkey2b217142014-12-15 09:24:24 -0800835 assertThat(result, matchesIntent(intent));
Ray Milkey05b169d2015-08-13 14:33:33 -0700836
837 // Test get using numeric value
Jian Li9d616492016-03-09 10:52:49 -0800838 final String responseNumeric = wt.path("intents/" + APP_ID.name()
839 + "/0x0").request().get(String.class);
Jian Li80cfe452016-01-14 16:04:58 -0800840 final JsonObject resultNumeric = Json.parse(responseNumeric).asObject();
Ray Milkey05b169d2015-08-13 14:33:33 -0700841 assertThat(resultNumeric, matchesIntent(intent));
Ray Milkey2b217142014-12-15 09:24:24 -0800842 }
843
844 /**
Author Namee252a002016-09-26 22:42:24 +0530845 * Tests the result of a rest api GET for related flows for single intent.
846 */
847 @Test
848 public void testRelatedFlowsForIntents() {
849 List<FlowEntry> flowEntries = new ArrayList<>();
850 flowEntries.add(flow1);
851 flowEntries.add(flow2);
852 List<List<FlowEntry>> paths = new ArrayList<>();
853 paths.add(flowEntries);
854 List<FlowRule> flowRules = new ArrayList<>();
855 flowRules.add(flowRule1);
856 flowRules.add(flowRule2);
857 FlowRuleIntent flowRuleIntent = new FlowRuleIntent(
858 APP_ID,
Ray Milkey39f78b62018-01-05 15:17:37 -0800859 null,
Author Namee252a002016-09-26 22:42:24 +0530860 flowRules,
Ray Milkey39f78b62018-01-05 15:17:37 -0800861 new HashSet<NetworkResource>(),
862 PathIntent.ProtectionType.PRIMARY,
863 null);
Author Namee252a002016-09-26 22:42:24 +0530864 Intent intent = new MockIntent(3L);
865 installableIntents.add(flowRuleIntent);
866 intents.add(intent);
867
868 expect(mockIntentService.getIntent(Key.of(0, APP_ID)))
869 .andReturn(intent)
870 .anyTimes();
871 expect(mockIntentService.getIntent(Key.of("0", APP_ID)))
872 .andReturn(intent)
873 .anyTimes();
874 expect(mockIntentService.getIntent(Key.of(0, APP_ID)))
875 .andReturn(intent)
876 .anyTimes();
877 expect(mockIntentService.getIntent(Key.of("0x0", APP_ID)))
878 .andReturn(null)
879 .anyTimes();
880 expect(mockIntentService.getInstallableIntents(intent.key()))
881 .andReturn(installableIntents)
882 .anyTimes();
883 replay(mockIntentService);
884
885 expect(mockFlowService.getFlowEntries(deviceId1))
886 .andReturn(flowEntries).anyTimes();
887 replay(mockFlowService);
888
889 expect(mockCoreService.getAppId(APP_ID.name()))
890 .andReturn(APP_ID).anyTimes();
891 expect(mockCoreService.getAppId(APP_ID.id()))
892 .andReturn(APP_ID).anyTimes();
893 replay(mockCoreService);
894
895 final WebTarget wt = target();
896
897 // Test get using key string
898 final String response = wt.path("intents/relatedflows/" + APP_ID.name()
899 + "/0").request().get(String.class);
900 final JsonObject result = Json.parse(response).asObject();
901 assertThat(result, matchesRelatedFlowEntries(paths, APP_ID.name()));
902
903 // Test get using numeric value
904 final String responseNumeric = wt.path("intents/relatedflows/" + APP_ID.name()
905 + "/0x0").request().get(String.class);
906 final JsonObject resultNumeric = Json.parse(responseNumeric).asObject();
907 assertThat(resultNumeric, matchesRelatedFlowEntries(paths, APP_ID.name()));
908 }
909
910 /**
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +0200911 * Tests the result of a rest api GET for intent installables.
912 */
913 @Test
914 public void testIntentInstallables() {
915
916 Link link1 = DefaultLink.builder()
917 .type(Link.Type.DIRECT)
918 .providerId(ProviderId.NONE)
919 .src(connectPoint1)
920 .dst(connectPoint2)
921 .build();
922
923 Link link2 = DefaultLink.builder()
924 .type(Link.Type.DIRECT)
925 .providerId(ProviderId.NONE)
926 .src(connectPoint3)
927 .dst(connectPoint4)
928 .build();
929
930 Set<NetworkResource> resources = new HashSet<>();
931 resources.add(link1);
932 resources.add(link2);
933
934 FlowRuleIntent flowRuleIntent = new FlowRuleIntent(
935 APP_ID,
Ray Milkey39f78b62018-01-05 15:17:37 -0800936 null,
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +0200937 new ArrayList<>(),
Ray Milkey39f78b62018-01-05 15:17:37 -0800938 resources,
939 PathIntent.ProtectionType.PRIMARY,
940 null);
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +0200941
942 Intent intent = new MockIntent(MockIntent.nextId());
943 Long intentId = intent.id().id();
944 installableIntents.add(flowRuleIntent);
945 intents.add(intent);
946
947 expect(mockIntentService.getIntent(Key.of(intentId, APP_ID)))
948 .andReturn(intent)
949 .anyTimes();
950 expect(mockIntentService.getIntent(Key.of(intentId.toString(), APP_ID)))
951 .andReturn(intent)
952 .anyTimes();
953 expect(mockIntentService.getIntent(Key.of(intentId, APP_ID)))
954 .andReturn(intent)
955 .anyTimes();
956 expect(mockIntentService.getIntent(Key.of(Long.toHexString(intentId), APP_ID)))
957 .andReturn(null)
958 .anyTimes();
959 expect(mockIntentService.getInstallableIntents(intent.key()))
960 .andReturn(installableIntents)
961 .anyTimes();
962 replay(mockIntentService);
963
964 replay(mockFlowService);
965
966 expect(mockCoreService.getAppId(APP_ID.name()))
967 .andReturn(APP_ID).anyTimes();
968 expect(mockCoreService.getAppId(APP_ID.id()))
969 .andReturn(APP_ID).anyTimes();
970 replay(mockCoreService);
971
972 final WebTarget wt = target();
973
974 // Test get using key string
975 final String response = wt.path("intents/installables/" + APP_ID.name()
976 + "/" + intentId).request().get(String.class);
977 final JsonObject result = Json.parse(response).asObject();
978 assertThat(result.get(INSTALLABLES).asArray(), hasIntent(flowRuleIntent));
979
980 // Test get using numeric value
981 final String responseNumeric = wt.path("intents/installables/" + APP_ID.name()
982 + "/" + Long.toHexString(intentId)).request().get(String.class);
983 final JsonObject resultNumeric = Json.parse(responseNumeric).asObject();
984 assertThat(resultNumeric.get(INSTALLABLES).asArray(), hasIntent(flowRuleIntent));
985 }
986
987 /**
Ray Milkey2b217142014-12-15 09:24:24 -0800988 * Tests that a fetch of a non-existent intent object throws an exception.
989 */
990 @Test
991 public void testBadGet() {
992
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800993 expect(mockIntentService.getIntent(Key.of(0, APP_ID)))
Ray Milkey2b217142014-12-15 09:24:24 -0800994 .andReturn(null)
995 .anyTimes();
996 replay(mockIntentService);
997
Jian Li9d616492016-03-09 10:52:49 -0800998 WebTarget wt = target();
Ray Milkey2b217142014-12-15 09:24:24 -0800999 try {
Jian Li9d616492016-03-09 10:52:49 -08001000 wt.path("intents/0").request().get(String.class);
Ray Milkey2b217142014-12-15 09:24:24 -08001001 fail("Fetch of non-existent intent did not throw an exception");
Jian Li9d616492016-03-09 10:52:49 -08001002 } catch (NotFoundException ex) {
Ray Milkey2b217142014-12-15 09:24:24 -08001003 assertThat(ex.getMessage(),
Jian Li9d616492016-03-09 10:52:49 -08001004 containsString("HTTP 404 Not Found"));
Ray Milkey2b217142014-12-15 09:24:24 -08001005 }
1006 }
Ray Milkeyb82c42b2015-06-30 09:42:20 -07001007
1008 /**
1009 * Tests creating an intent with POST.
1010 */
1011 @Test
1012 public void testPost() {
Ray Milkeyf7cb4012015-07-20 13:01:07 -07001013 ApplicationId testId = new DefaultApplicationId(2, "myApp");
1014 expect(mockCoreService.getAppId("myApp"))
1015 .andReturn(testId);
Ray Milkeyb82c42b2015-06-30 09:42:20 -07001016 replay(mockCoreService);
1017
1018 mockIntentService.submit(anyObject());
1019 expectLastCall();
1020 replay(mockIntentService);
1021
1022 InputStream jsonStream = IntentsResourceTest.class
1023 .getResourceAsStream("post-intent.json");
Jian Li9d616492016-03-09 10:52:49 -08001024 WebTarget wt = target();
Ray Milkeyb82c42b2015-06-30 09:42:20 -07001025
Jian Li9d616492016-03-09 10:52:49 -08001026 Response response = wt.path("intents")
1027 .request(MediaType.APPLICATION_JSON_TYPE)
1028 .post(Entity.json(jsonStream));
Ray Milkeyb82c42b2015-06-30 09:42:20 -07001029 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
1030 String location = response.getLocation().getPath();
Ray Milkey8d076402015-08-31 15:43:18 -07001031 assertThat(location, Matchers.startsWith("/intents/myApp/"));
Ray Milkeyb82c42b2015-06-30 09:42:20 -07001032 }
Ray Milkey7b158512015-07-21 16:32:43 -07001033
1034 /**
Ray Milkey05b169d2015-08-13 14:33:33 -07001035 * Tests creating an intent with POST and illegal JSON.
1036 */
1037 @Test
1038 public void testBadPost() {
1039 replay(mockCoreService);
1040 replay(mockIntentService);
1041
1042 String json = "this is invalid!";
Jian Li9d616492016-03-09 10:52:49 -08001043 WebTarget wt = target();
Ray Milkey05b169d2015-08-13 14:33:33 -07001044
Jian Li9d616492016-03-09 10:52:49 -08001045 Response response = wt.path("intents")
1046 .request(MediaType.APPLICATION_JSON_TYPE)
1047 .post(Entity.json(json));
Ray Milkey05b169d2015-08-13 14:33:33 -07001048 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_BAD_REQUEST));
1049 }
1050
1051 /**
Ray Milkey7b158512015-07-21 16:32:43 -07001052 * Tests removing an intent with DELETE.
1053 */
1054 @Test
1055 public void testRemove() {
1056 final HashSet<NetworkResource> resources = new HashSet<>();
1057 resources.add(new MockResource(1));
1058 resources.add(new MockResource(2));
1059 resources.add(new MockResource(3));
1060 final Intent intent = new MockIntent(3L, resources);
1061 final ApplicationId appId = new DefaultApplicationId(2, "app");
1062 IntentService fakeManager = new FakeIntentManager();
1063
1064 expect(mockCoreService.getAppId("app"))
1065 .andReturn(appId).once();
1066 replay(mockCoreService);
1067
1068 mockIntentService.withdraw(anyObject());
1069 expectLastCall().andDelegateTo(fakeManager).once();
1070 expect(mockIntentService.getIntent(Key.of(2, appId)))
1071 .andReturn(intent)
1072 .once();
1073 expect(mockIntentService.getIntent(Key.of("0x2", appId)))
1074 .andReturn(null)
1075 .once();
1076
1077 mockIntentService.addListener(anyObject());
1078 expectLastCall().andDelegateTo(fakeManager).once();
1079 mockIntentService.removeListener(anyObject());
1080 expectLastCall().andDelegateTo(fakeManager).once();
1081
1082 replay(mockIntentService);
1083
Jian Li9d616492016-03-09 10:52:49 -08001084 WebTarget wt = target();
Ray Milkey7b158512015-07-21 16:32:43 -07001085
Jian Li9d616492016-03-09 10:52:49 -08001086 Response response = wt.path("intents/app/0x2")
Ray Milkey7c251822016-04-06 17:38:25 -07001087 .request(MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN)
Jian Li9d616492016-03-09 10:52:49 -08001088 .delete();
Ray Milkey7b158512015-07-21 16:32:43 -07001089 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NO_CONTENT));
1090 }
Ray Milkey05b169d2015-08-13 14:33:33 -07001091
1092 /**
1093 * Tests removal of a non existent intent with DELETE.
1094 */
1095 @Test
1096 public void testBadRemove() {
1097 final ApplicationId appId = new DefaultApplicationId(2, "app");
1098
1099 expect(mockCoreService.getAppId("app"))
1100 .andReturn(appId).once();
1101 replay(mockCoreService);
1102
1103 expect(mockIntentService.getIntent(Key.of(2, appId)))
1104 .andReturn(null)
1105 .once();
1106 expect(mockIntentService.getIntent(Key.of("0x2", appId)))
1107 .andReturn(null)
1108 .once();
1109
1110 replay(mockIntentService);
1111
Jian Li9d616492016-03-09 10:52:49 -08001112 WebTarget wt = target();
Ray Milkey05b169d2015-08-13 14:33:33 -07001113
Jian Li9d616492016-03-09 10:52:49 -08001114 Response response = wt.path("intents/app/0x2")
Ray Milkey7c251822016-04-06 17:38:25 -07001115 .request(MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN)
Jian Li9d616492016-03-09 10:52:49 -08001116 .delete();
Ray Milkey05b169d2015-08-13 14:33:33 -07001117 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NO_CONTENT));
1118 }
1119
dvaddire95c84ed2017-06-14 15:42:24 +05301120 @Test
1121 public void testIntentsMiniSummary() {
1122 final Intent intent1 = new MockIntent(1L, Collections.emptyList());
1123 final HashSet<NetworkResource> resources = new HashSet<>();
1124 resources.add(new MockResource(1));
1125 resources.add(new MockResource(2));
1126 resources.add(new MockResource(3));
1127 final Intent intent2 = new MockIntent(2L, resources);
1128 intents.add(intent1);
1129 intents.add(intent2);
1130 final WebTarget wt = target();
1131 replay(mockIntentService);
1132 final String response = wt.path("intents/minisummary").request().get(String.class);
1133 assertThat(response, containsString("{\"All\":{"));
1134 final JsonObject result = Json.parse(response).asObject();
1135 assertThat(result, notNullValue());
1136 assertThat(result.names(), hasSize(2));
1137 assertThat(result.names().get(0), containsString("All"));
1138 JsonObject jsonIntents = (JsonObject) result.get("All");
1139 assertThat(jsonIntents, notNullValue());
1140 assertThat(jsonIntents.get("total").toString(), containsString("2"));
1141 jsonIntents = (JsonObject) result.get("Mock");
1142 assertThat(jsonIntents, notNullValue());
1143 assertThat(jsonIntents.get("installed").toString(), containsString("2"));
1144 }
Ray Milkey2b217142014-12-15 09:24:24 -08001145}
dvaddire95c84ed2017-06-14 15:42:24 +05301146