blob: e57af12dc1948599437af220b295c7df672839be [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;
51import org.onosproject.net.flow.FlowRuleExtPayLoad;
52import org.onosproject.net.flow.FlowRuleService;
Carmelo Cascone41605742017-06-19 15:46:44 +090053import org.onosproject.net.flow.TableId;
Author Namee252a002016-09-26 22:42:24 +053054import org.onosproject.net.flow.TrafficSelector;
55import org.onosproject.net.flow.TrafficTreatment;
56import org.onosproject.net.flow.criteria.Criterion;
57import org.onosproject.net.flow.instructions.Instruction;
Ray Milkey7b158512015-07-21 16:32:43 -070058import org.onosproject.net.intent.FakeIntentManager;
Author Namee252a002016-09-26 22:42:24 +053059import org.onosproject.net.intent.FlowRuleIntent;
Ray Milkey2b217142014-12-15 09:24:24 -080060import org.onosproject.net.intent.Intent;
Ray Milkey2b217142014-12-15 09:24:24 -080061import org.onosproject.net.intent.IntentService;
Ray Milkey1534f8d2015-05-13 15:42:50 -070062import org.onosproject.net.intent.IntentState;
Ray Milkeyf9af43c2015-02-09 16:45:48 -080063import org.onosproject.net.intent.Key;
Thomas Vachuska2048c1f2017-05-10 19:32:22 -070064import org.onosproject.net.intent.MockIdGenerator;
Ray Milkey39f78b62018-01-05 15:17:37 -080065import org.onosproject.net.intent.PathIntent;
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +020066import org.onosproject.net.provider.ProviderId;
Ray Milkey2b217142014-12-15 09:24:24 -080067
dvaddire95c84ed2017-06-14 15:42:24 +053068
Author Namee252a002016-09-26 22:42:24 +053069import javax.ws.rs.NotFoundException;
70import javax.ws.rs.client.Entity;
71import javax.ws.rs.client.WebTarget;
72import javax.ws.rs.core.MediaType;
73import javax.ws.rs.core.Response;
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +020074import java.io.IOException;
Author Namee252a002016-09-26 22:42:24 +053075import java.io.InputStream;
76import java.net.HttpURLConnection;
77import java.util.ArrayList;
78import java.util.Collections;
79import java.util.HashSet;
80import java.util.List;
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +020081import java.util.Set;
Author Namee252a002016-09-26 22:42:24 +053082import java.util.concurrent.TimeUnit;
Ray Milkey2b217142014-12-15 09:24:24 -080083
Author Namee252a002016-09-26 22:42:24 +053084import static java.util.concurrent.TimeUnit.SECONDS;
85import static org.easymock.EasyMock.*;
86import static org.hamcrest.Matchers.*;
Ray Milkey2b217142014-12-15 09:24:24 -080087import static org.junit.Assert.assertThat;
88import static org.junit.Assert.fail;
Ray Milkey43a28222015-02-23 13:57:58 -080089import static org.onosproject.net.intent.IntentTestsMocks.MockIntent;
Ray Milkey2b217142014-12-15 09:24:24 -080090
91/**
92 * Unit tests for Intents REST APIs.
93 */
Ray Milkey9c3d3362015-01-28 10:39:56 -080094public class IntentsResourceTest extends ResourceTest {
Author Namee252a002016-09-26 22:42:24 +053095
96
97 private static final String APPID = "appId";
98 private static final String CRITERIA = "criteria";
99 private static final String DEVICE_ID = "deviceId";
100 private static final String ID = "id";
101 private static final String INSTRUCTIONS = "instructions";
102 private static final String PATHS = "paths";
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +0200103 private static final String INSTALLABLES = "installables";
104 private static final String RESOURCES = "resources";
105 private static final String DEVICE = "device";
106 private static final String PORT = "port";
107 private static final String SRC = "src";
108 private static final String DST = "dst";
Author Namee252a002016-09-26 22:42:24 +0530109 private static final String SELECTOR = "selector";
110 private static final String SPACE = " ";
111 private static final String TREATMENT = "treatment";
112 private static final String TYPE = "type";
113
Ray Milkey2b217142014-12-15 09:24:24 -0800114 final IntentService mockIntentService = createMock(IntentService.class);
Ayaka Koshibec06c89b2015-02-10 19:25:41 -0800115 final CoreService mockCoreService = createMock(CoreService.class);
Author Namee252a002016-09-26 22:42:24 +0530116 final FlowRuleService mockFlowService = createMock(FlowRuleService.class);
Ray Milkey2b217142014-12-15 09:24:24 -0800117 final HashSet<Intent> intents = new HashSet<>();
Author Namee252a002016-09-26 22:42:24 +0530118 final List<org.onosproject.net.intent.Intent> installableIntents = new ArrayList<>();
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800119 private static final ApplicationId APP_ID = new DefaultApplicationId(1, "test");
Ray Milkey2b217142014-12-15 09:24:24 -0800120
Author Namee252a002016-09-26 22:42:24 +0530121 final DeviceId deviceId1 = DeviceId.deviceId("1");
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +0200122 final DeviceId deviceId2 = DeviceId.deviceId("2");
123 final DeviceId deviceId3 = DeviceId.deviceId("3");
124
125 final ConnectPoint connectPoint1 = new ConnectPoint(deviceId1, PortNumber.portNumber(1L));
126 final ConnectPoint connectPoint2 = new ConnectPoint(deviceId2, PortNumber.portNumber(1L));
127 final ConnectPoint connectPoint3 = new ConnectPoint(deviceId2, PortNumber.portNumber(2L));
128 final ConnectPoint connectPoint4 = new ConnectPoint(deviceId3, PortNumber.portNumber(1L));
Author Namee252a002016-09-26 22:42:24 +0530129
130 final TrafficTreatment treatment1 = DefaultTrafficTreatment.builder()
131 .setEthDst(MacAddress.BROADCAST)
132 .build();
133 final TrafficTreatment treatment2 = DefaultTrafficTreatment.builder()
134 .setEthDst(MacAddress.IPV4_MULTICAST)
135 .build();
136
137 final TrafficSelector selector1 = DefaultTrafficSelector.builder()
138 .matchEthType((short) 3)
139 .matchIPProtocol((byte) 9)
140 .build();
141 final TrafficSelector selector2 = DefaultTrafficSelector.builder()
142 .matchEthType((short) 4)
143 .matchIPProtocol((byte) 10)
144 .build();
145
146 final MockFlowEntry flow1 = new MockFlowEntry(deviceId1, 1, treatment1, selector1);
147 final MockFlowEntry flow2 = new MockFlowEntry(deviceId1, 2, treatment2, selector2);
148
149 final MockFlowRule flowRule1 = new MockFlowRule(deviceId1, 1, treatment1, selector1);
150 final MockFlowRule flowRule2 = new MockFlowRule(deviceId1, 2, treatment2, selector2);
151
Ray Milkey2b217142014-12-15 09:24:24 -0800152 private class MockResource implements NetworkResource {
153 int id;
154
155 MockResource(int id) {
156 this.id = id;
157 }
158
Ayaka Koshibec06c89b2015-02-10 19:25:41 -0800159 @Override
Ray Milkey2b217142014-12-15 09:24:24 -0800160 public String toString() {
161 return "Resource " + Integer.toString(id);
162 }
163 }
164
Ray Milkey2b217142014-12-15 09:24:24 -0800165 /**
Author Namee252a002016-09-26 22:42:24 +0530166 * Mock class for a flow entry.
167 */
Ray Milkey634eb172017-04-05 14:48:50 -0700168 private static class MockFlowEntry extends FlowEntryAdapter {
Author Namee252a002016-09-26 22:42:24 +0530169 final DeviceId deviceId;
170 final long baseValue;
171 TrafficTreatment treatment;
172 TrafficSelector selector;
173
174 public MockFlowEntry(DeviceId deviceId, long id,
175 TrafficTreatment treatment,
176 TrafficSelector selector) {
177 this.deviceId = deviceId;
178 this.baseValue = id * 100;
179 this.treatment = treatment;
180 this.selector = selector;
181 }
182
183 @Override
Author Namee252a002016-09-26 22:42:24 +0530184 public long life() {
185 return life(SECONDS);
186 }
187
188 @Override
kalagesa42019542017-03-14 18:00:47 +0530189 public FlowLiveType liveType() {
190 return FlowLiveType.IMMEDIATE;
191 }
192
193 @Override
Author Namee252a002016-09-26 22:42:24 +0530194 public long life(TimeUnit timeUnit) {
195 return SECONDS.convert(baseValue + 11, timeUnit);
196 }
197
198 @Override
199 public long packets() {
200 return baseValue + 22;
201 }
202
203 @Override
204 public long bytes() {
205 return baseValue + 33;
206 }
207
208 @Override
209 public long lastSeen() {
210 return baseValue + 44;
211 }
212
213 @Override
Author Namee252a002016-09-26 22:42:24 +0530214 public FlowId id() {
215 final long id = baseValue + 55;
216 return FlowId.valueOf(id);
217 }
218
219 @Override
220 public GroupId groupId() {
Yi Tsengfa394de2017-02-01 11:26:40 -0800221 return new GroupId(3);
Author Namee252a002016-09-26 22:42:24 +0530222 }
223
224 @Override
225 public short appId() {
226 return 1;
227 }
228
229 @Override
230 public int priority() {
231 return (int) (baseValue + 66);
232 }
233
234 @Override
235 public DeviceId deviceId() {
236 return deviceId;
237 }
238
239 @Override
240 public TrafficSelector selector() {
241 return selector;
242 }
243
244 @Override
245 public TrafficTreatment treatment() {
246 return treatment;
247 }
248
249 @Override
250 public int timeout() {
251 return (int) (baseValue + 77);
252 }
253
Author Namee252a002016-09-26 22:42:24 +0530254
255 @Override
256 public boolean exactMatch(FlowRule rule) {
257 return this.appId() == rule.appId() &&
258 this.deviceId().equals(rule.deviceId()) &&
259 this.id().equals(rule.id()) &&
260 this.treatment.equals(rule.treatment()) &&
261 this.selector().equals(rule.selector());
262 }
263
264 @Override
Author Namee252a002016-09-26 22:42:24 +0530265 public String toString() {
266 return id().id().toString();
267 }
268 }
269
270 /**
271 * Mock class for a flow rule.
272 */
273 private static class MockFlowRule implements FlowRule {
274
275 final DeviceId deviceId;
276 final long baseValue;
277 TrafficTreatment treatment;
278 TrafficSelector selector;
279
280 public MockFlowRule(DeviceId deviceId,
281 long id,
282 TrafficTreatment treatment,
283 TrafficSelector selector) {
284 this.deviceId = deviceId;
285 this.baseValue = id * 100;
286 this.treatment = treatment;
287 this.selector = selector;
288 }
289
290 @Override
291 public FlowId id() {
292 long id = baseValue + 55;
293 return FlowId.valueOf(id);
294 }
295
296 @Override
297 public short appId() {
298 return 1;
299 }
300
301 @Override
302 public GroupId groupId() {
Yi Tsengfa394de2017-02-01 11:26:40 -0800303 return new GroupId(3);
Author Namee252a002016-09-26 22:42:24 +0530304 }
305
306 @Override
307 public int priority() {
308 return 0;
309 }
310
311 @Override
312 public DeviceId deviceId() {
313 return deviceId;
314 }
315
316 @Override
317 public TrafficSelector selector() {
318 return selector;
319 }
320
321 @Override
322 public TrafficTreatment treatment() {
323 return treatment;
324 }
325
326 @Override
327 public int timeout() {
328 return (int) (baseValue + 77);
329 }
330
331 @Override
332 public int hardTimeout() {
333 return 0;
334 }
335
336 @Override
337 public FlowRemoveReason reason() {
338 return FlowRemoveReason.NO_REASON;
339 }
340
341 @Override
342 public boolean isPermanent() {
343 return false;
344 }
345
346 @Override
347 public int tableId() {
348 return 0;
349 }
350
351 @Override
Carmelo Cascone41605742017-06-19 15:46:44 +0900352 public TableId table() {
353 return DEFAULT_TABLE;
354 }
355
356 @Override
Author Namee252a002016-09-26 22:42:24 +0530357 public boolean exactMatch(FlowRule rule) {
358 return false;
359 }
360
361 @Override
362 public FlowRuleExtPayLoad payLoad() {
363 return null;
364 }
365 }
366
367 /**
Ray Milkey2b217142014-12-15 09:24:24 -0800368 * Hamcrest matcher to check that an intent representation in JSON matches
369 * the actual intent.
370 */
371 public static class IntentJsonMatcher extends TypeSafeMatcher<JsonObject> {
372 private final Intent intent;
373 private String reason = "";
374
375 public IntentJsonMatcher(Intent intentValue) {
376 intent = intentValue;
377 }
378
379 @Override
380 public boolean matchesSafely(JsonObject jsonIntent) {
381 // check id
382 final String jsonId = jsonIntent.get("id").asString();
383 if (!jsonId.equals(intent.id().toString())) {
384 reason = "id " + intent.id().toString();
385 return false;
386 }
387
388 // check application id
Ray Milkeyf7cb4012015-07-20 13:01:07 -0700389
Ray Milkey2b217142014-12-15 09:24:24 -0800390 final String jsonAppId = jsonIntent.get("appId").asString();
Ray Milkeyf7cb4012015-07-20 13:01:07 -0700391 final String appId = intent.appId().name();
392 if (!jsonAppId.equals(appId)) {
393 reason = "appId was " + jsonAppId;
Ray Milkey2b217142014-12-15 09:24:24 -0800394 return false;
395 }
396
397 // check intent type
398 final String jsonType = jsonIntent.get("type").asString();
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +0200399 if (!intent.getClass().getSimpleName().equals(jsonType)) {
Ray Milkey2b217142014-12-15 09:24:24 -0800400 reason = "type MockIntent";
401 return false;
402 }
403
Ray Milkey1534f8d2015-05-13 15:42:50 -0700404 // check state field
405 final String jsonState = jsonIntent.get("state").asString();
Jon Halla3fcf672017-03-28 16:53:22 -0700406 if (!"INSTALLED".equals(jsonState)) {
Ray Milkey1534f8d2015-05-13 15:42:50 -0700407 reason = "state INSTALLED";
408 return false;
409 }
410
Ray Milkey2b217142014-12-15 09:24:24 -0800411 // check resources array
412 final JsonArray jsonResources = jsonIntent.get("resources").asArray();
413 if (intent.resources() != null) {
414 if (intent.resources().size() != jsonResources.size()) {
415 reason = "resources array size of " + Integer.toString(intent.resources().size());
416 return false;
417 }
418 for (final NetworkResource resource : intent.resources()) {
419 boolean resourceFound = false;
420 final String resourceString = resource.toString();
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +0200421
422 if (resource instanceof Link) {
423 final Link resourceLink = (Link) resource;
424 MockCodecContext codecContext = new MockCodecContext();
425
426 for (int resourceIndex = 0; resourceIndex < jsonResources.size(); resourceIndex++) {
427 final ObjectNode value;
428 try {
429 value = (ObjectNode) codecContext.mapper()
430 .readTree(jsonResources.get(resourceIndex).toString());
431 } catch (IOException e) {
432 reason = "bad json";
433 return false;
434 }
435 final Link link = codecContext.codec(Link.class).decode(value, codecContext);
436 if (resourceLink.equals(link)) {
437 resourceFound = true;
438 }
439 }
440 } else {
441
442 for (int resourceIndex = 0; resourceIndex < jsonResources.size(); resourceIndex++) {
443 final JsonValue value = jsonResources.get(resourceIndex);
444 if (value.asString().equals(resourceString)) {
445 resourceFound = true;
446 }
Ray Milkey2b217142014-12-15 09:24:24 -0800447 }
448 }
449 if (!resourceFound) {
450 reason = "resource " + resourceString;
451 return false;
452 }
453 }
454 } else if (jsonResources.size() != 0) {
455 reason = "resources array empty";
456 return false;
457 }
458 return true;
459 }
460
461 @Override
462 public void describeTo(Description description) {
463 description.appendText(reason);
464 }
465 }
466
467 /**
468 * Factory to allocate an intent matcher.
469 *
470 * @param intent intent object we are looking for
471 * @return matcher
472 */
473 private static IntentJsonMatcher matchesIntent(Intent intent) {
474 return new IntentJsonMatcher(intent);
475 }
476
477 /**
Author Namee252a002016-09-26 22:42:24 +0530478 * Factory to allocate an IntentRelatedFlows matcher.
479 *
dvaddire95c84ed2017-06-14 15:42:24 +0530480 * @param pathEntries list of path conatining flow entries of a particular intent
Author Namee252a002016-09-26 22:42:24 +0530481 * @param expectedAppId expected app id we are looking for
482 * @return matcher
483 */
484 private static IntentStatsJsonMatcher matchesRelatedFlowEntries(
485 List<List<FlowEntry>> pathEntries,
486 final String expectedAppId) {
487 return new IntentStatsJsonMatcher(pathEntries, expectedAppId);
488 }
489
490 /**
491 * Hamcrest matcher to check that an list of flowEntries in JSON matches
492 * the actual list of flow entries.
493 */
494 public static class IntentStatsJsonMatcher extends
495 TypeSafeMatcher<JsonObject> {
496
497 private final List<List<FlowEntry>> pathEntries;
498 private final String expectedAppId;
499 private String reason = "";
500
501 public IntentStatsJsonMatcher(
502 final List<List<FlowEntry>> pathEntries,
503 final String expectedAppId) {
504 this.pathEntries = pathEntries;
505 this.expectedAppId = expectedAppId;
506 }
507
508 @Override
509 public boolean matchesSafely(JsonObject jsonIntent) {
510 int jsonPathIndex = 0;
511 JsonArray jsonPaths = jsonIntent.get(PATHS).asArray();
512
513 if (pathEntries != null) {
514
rohitsharanfd747602017-01-23 21:57:28 +0530515 if (pathEntries.size() == 0) {
516 reason = "pathEntries array empty";
517 return false;
518 }
519
Author Namee252a002016-09-26 22:42:24 +0530520 if (pathEntries.size() != jsonPaths.size()) {
521 reason = "path entries array size of " +
522 Integer.toString(pathEntries.size());
523 return false;
524 }
525
526 for (List<FlowEntry> flowEntries : pathEntries) {
527 JsonArray jsonFlowEntries = jsonPaths.get(
528 jsonPathIndex++).asArray();
529
530 if (flowEntries.size() != jsonFlowEntries.size()) {
531 reason = "flow entries array size of " +
532 Integer.toString(pathEntries.size());
533
534 return false;
535 }
536
537 int jsonFlowEntryIndex = 0;
538 for (FlowEntry flow : flowEntries) {
539
540 JsonObject jsonFlow = jsonFlowEntries.get(
541 jsonFlowEntryIndex++).asObject();
542
543 String jsonId = jsonFlow.get(ID).asString();
544 String flowId = Long.toString(flow.id().value());
545 if (!jsonId.equals(flowId)) {
546 reason = ID + SPACE + flow.id();
547 return false;
548 }
549
550 // check application id
551 String jsonAppId = jsonFlow.get(APPID).asString();
552 if (!jsonAppId.equals(expectedAppId)) {
553 reason = APPID + SPACE + Short.toString(flow.appId());
554 return false;
555 }
556
557 // check device id
558 String jsonDeviceId =
559 jsonFlow.get(DEVICE_ID).asString();
560
561 if (!jsonDeviceId.equals(flow.deviceId().toString())) {
562 reason = DEVICE_ID + SPACE + flow.deviceId();
563 return false;
564 }
565
566 if (!checkFlowTreatment(flow, jsonFlow)) {
567 return false;
568 }
569
570 if (!checkFlowSelector(flow, jsonFlow)) {
571 return false;
572 }
573
574 }
575
576 }
rohitsharanfd747602017-01-23 21:57:28 +0530577 } else {
Author Namee252a002016-09-26 22:42:24 +0530578 reason = "pathEntries array empty";
579 return false;
580 }
581
582 return true;
583 }
584
585 // check treatment and instructions array.
586 private boolean checkFlowTreatment(FlowEntry flow, JsonObject jsonFlow) {
587
588 if (flow.treatment() != null) {
589 JsonObject jsonTreatment =
590 jsonFlow.get(TREATMENT).asObject();
591 JsonArray jsonInstructions =
592 jsonTreatment.get(INSTRUCTIONS).asArray();
593
594 if (flow.treatment().immediate().size() !=
595 jsonInstructions.size()) {
596 reason = "instructions array size of " +
597 flow.treatment().immediate().size();
598
599 return false;
600 }
601 for (Instruction instruction :
602 flow.treatment().immediate()) {
603 boolean instructionFound = false;
604 for (int instructionIndex = 0;
605 instructionIndex < jsonInstructions.size();
606 instructionIndex++) {
607 String jsonType =
608 jsonInstructions.get(instructionIndex)
609 .asObject().get(TYPE).asString();
610
611 String instructionType =
612 instruction.type().name();
613
614 if (jsonType.equals(instructionType)) {
615 instructionFound = true;
616 }
617 }
618 if (!instructionFound) {
619 reason = INSTRUCTIONS + SPACE + instruction;
620 return false;
621 }
622 }
623 }
624 return true;
625 }
626
627 // check selector and criteria array.
628 private boolean checkFlowSelector(FlowEntry flow, JsonObject jsonFlow) {
629
630 if (flow.selector() != null) {
631 JsonObject jsonTreatment =
632 jsonFlow.get(SELECTOR).asObject();
633
634 JsonArray jsonCriteria =
635 jsonTreatment.get(CRITERIA).asArray();
636
637 if (flow.selector().criteria().size() != jsonCriteria.size()) {
638 reason = CRITERIA + " array size of " +
639 Integer.toString(flow.selector().criteria().size());
640 return false;
641 }
642 for (Criterion criterion : flow.selector().criteria()) {
643 boolean criterionFound = false;
644
645 for (int criterionIndex = 0;
646 criterionIndex < jsonCriteria.size();
647 criterionIndex++) {
648 String jsonType =
649 jsonCriteria.get(criterionIndex)
650 .asObject().get(TYPE).asString();
651 String criterionType = criterion.type().name();
652 if (jsonType.equals(criterionType)) {
653 criterionFound = true;
654 }
655 }
656 if (!criterionFound) {
657 reason = "criterion " + criterion;
658 return false;
659 }
660 }
661 }
662 return true;
663 }
664
665 @Override
666 public void describeTo(Description description) {
667 description.appendText(reason);
668 }
669 }
670
671 /**
Ray Milkey2b217142014-12-15 09:24:24 -0800672 * Hamcrest matcher to check that an intent is represented properly in a JSON
673 * array of intents.
674 */
675 public static class IntentJsonArrayMatcher extends TypeSafeMatcher<JsonArray> {
676 private final Intent intent;
677 private String reason = "";
678
679 public IntentJsonArrayMatcher(Intent intentValue) {
680 intent = intentValue;
681 }
682
683 @Override
684 public boolean matchesSafely(JsonArray json) {
685 boolean intentFound = false;
Antonio Marsico4f68ec92017-03-09 11:16:32 +0100686 final int expectedAttributes = 6;
Ray Milkey2b217142014-12-15 09:24:24 -0800687 for (int jsonIntentIndex = 0; jsonIntentIndex < json.size();
688 jsonIntentIndex++) {
689
690 final JsonObject jsonIntent = json.get(jsonIntentIndex).asObject();
691
692 if (jsonIntent.names().size() != expectedAttributes) {
693 reason = "Found an intent with the wrong number of attributes";
694 return false;
695 }
696
697 final String jsonIntentId = jsonIntent.get("id").asString();
698 if (jsonIntentId.equals(intent.id().toString())) {
699 intentFound = true;
700
701 // We found the correct intent, check attribute values
702 assertThat(jsonIntent, matchesIntent(intent));
703 }
704 }
705 if (!intentFound) {
706 reason = "Intent with id " + intent.id().toString() + " not found";
707 return false;
708 } else {
709 return true;
710 }
711 }
712
713 @Override
714 public void describeTo(Description description) {
715 description.appendText(reason);
716 }
717 }
718
719 /**
720 * Factory to allocate an intent array matcher.
721 *
722 * @param intent intent object we are looking for
723 * @return matcher
724 */
725 private static IntentJsonArrayMatcher hasIntent(Intent intent) {
726 return new IntentJsonArrayMatcher(intent);
727 }
Ray Milkey4f5de002014-12-17 19:26:11 -0800728
Ray Milkeyed0b1662015-02-05 09:34:29 -0800729 /**
730 * Initializes test mocks and environment.
731 */
Ray Milkey2b217142014-12-15 09:24:24 -0800732 @Before
Ray Milkeyed0b1662015-02-05 09:34:29 -0800733 public void setUpTest() {
Ray Milkey2b217142014-12-15 09:24:24 -0800734 expect(mockIntentService.getIntents()).andReturn(intents).anyTimes();
Ray Milkey1534f8d2015-05-13 15:42:50 -0700735 expect(mockIntentService.getIntentState(anyObject()))
736 .andReturn(IntentState.INSTALLED)
737 .anyTimes();
Ray Milkey2b217142014-12-15 09:24:24 -0800738 // Register the services needed for the test
dvaddire95c84ed2017-06-14 15:42:24 +0530739 final CodecManager codecService = new CodecManager();
Ray Milkey2b217142014-12-15 09:24:24 -0800740 codecService.activate();
741 ServiceDirectory testDirectory =
742 new TestServiceDirectory()
743 .add(IntentService.class, mockIntentService)
Author Namee252a002016-09-26 22:42:24 +0530744 .add(FlowRuleService.class, mockFlowService)
Ayaka Koshibec06c89b2015-02-10 19:25:41 -0800745 .add(CodecService.class, codecService)
746 .add(CoreService.class, mockCoreService);
Ray Milkey2b217142014-12-15 09:24:24 -0800747
Ray Milkey094a1352018-01-22 14:03:54 -0800748 setServiceDirectory(testDirectory);
Ray Milkey2b217142014-12-15 09:24:24 -0800749
Thomas Vachuska2048c1f2017-05-10 19:32:22 -0700750 MockIdGenerator.cleanBind();
Ray Milkey2b217142014-12-15 09:24:24 -0800751 }
752
Ray Milkeyed0b1662015-02-05 09:34:29 -0800753 /**
754 * Tears down and verifies test mocks and environment.
755 */
Ray Milkey2b217142014-12-15 09:24:24 -0800756 @After
Ray Milkeyed0b1662015-02-05 09:34:29 -0800757 public void tearDownTest() {
Thomas Vachuska2048c1f2017-05-10 19:32:22 -0700758 MockIdGenerator.unbind();
Ray Milkey2b217142014-12-15 09:24:24 -0800759 verify(mockIntentService);
Ray Milkey2b217142014-12-15 09:24:24 -0800760 }
761
762 /**
763 * Tests the result of the rest api GET when there are no intents.
764 */
765 @Test
766 public void testIntentsEmptyArray() {
767 replay(mockIntentService);
Jian Li9d616492016-03-09 10:52:49 -0800768 final WebTarget wt = target();
769 final String response = wt.path("intents").request().get(String.class);
Ray Milkey2b217142014-12-15 09:24:24 -0800770 assertThat(response, is("{\"intents\":[]}"));
771 }
772
773 /**
774 * Tests the result of the rest api GET when intents are defined.
775 */
776 @Test
777 public void testIntentsArray() {
778 replay(mockIntentService);
779
Ray Milkey43a28222015-02-23 13:57:58 -0800780 final Intent intent1 = new MockIntent(1L, Collections.emptyList());
Ray Milkey2b217142014-12-15 09:24:24 -0800781 final HashSet<NetworkResource> resources = new HashSet<>();
782 resources.add(new MockResource(1));
783 resources.add(new MockResource(2));
784 resources.add(new MockResource(3));
Ray Milkey43a28222015-02-23 13:57:58 -0800785 final Intent intent2 = new MockIntent(2L, resources);
Ray Milkey2b217142014-12-15 09:24:24 -0800786
787 intents.add(intent1);
788 intents.add(intent2);
Jian Li9d616492016-03-09 10:52:49 -0800789 final WebTarget wt = target();
790 final String response = wt.path("intents").request().get(String.class);
Ray Milkey2b217142014-12-15 09:24:24 -0800791 assertThat(response, containsString("{\"intents\":["));
792
Jian Li80cfe452016-01-14 16:04:58 -0800793 final JsonObject result = Json.parse(response).asObject();
Ray Milkey2b217142014-12-15 09:24:24 -0800794 assertThat(result, notNullValue());
795
796 assertThat(result.names(), hasSize(1));
797 assertThat(result.names().get(0), is("intents"));
798
799 final JsonArray jsonIntents = result.get("intents").asArray();
800 assertThat(jsonIntents, notNullValue());
801
802 assertThat(jsonIntents, hasIntent(intent1));
803 assertThat(jsonIntents, hasIntent(intent2));
804 }
805
806 /**
807 * Tests the result of a rest api GET for a single intent.
808 */
809 @Test
810 public void testIntentsSingle() {
811 final HashSet<NetworkResource> resources = new HashSet<>();
812 resources.add(new MockResource(1));
813 resources.add(new MockResource(2));
814 resources.add(new MockResource(3));
Ray Milkey43a28222015-02-23 13:57:58 -0800815 final Intent intent = new MockIntent(3L, resources);
Ray Milkey2b217142014-12-15 09:24:24 -0800816
817 intents.add(intent);
818
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800819 expect(mockIntentService.getIntent(Key.of(0, APP_ID)))
Ray Milkey2b217142014-12-15 09:24:24 -0800820 .andReturn(intent)
821 .anyTimes();
Ayaka Koshibec06c89b2015-02-10 19:25:41 -0800822 expect(mockIntentService.getIntent(Key.of("0", APP_ID)))
823 .andReturn(intent)
824 .anyTimes();
Ray Milkey05b169d2015-08-13 14:33:33 -0700825 expect(mockIntentService.getIntent(Key.of(0, APP_ID)))
826 .andReturn(intent)
827 .anyTimes();
828 expect(mockIntentService.getIntent(Key.of("0x0", APP_ID)))
829 .andReturn(null)
830 .anyTimes();
Ray Milkey2b217142014-12-15 09:24:24 -0800831 replay(mockIntentService);
Ray Milkeyf7cb4012015-07-20 13:01:07 -0700832 expect(mockCoreService.getAppId(APP_ID.name()))
Ayaka Koshibec06c89b2015-02-10 19:25:41 -0800833 .andReturn(APP_ID).anyTimes();
834 replay(mockCoreService);
Jian Li9d616492016-03-09 10:52:49 -0800835 final WebTarget wt = target();
Ray Milkey05b169d2015-08-13 14:33:33 -0700836
837 // Test get using key string
Jian Li9d616492016-03-09 10:52:49 -0800838 final String response = wt.path("intents/" + APP_ID.name()
839 + "/0").request().get(String.class);
Jian Li80cfe452016-01-14 16:04:58 -0800840 final JsonObject result = Json.parse(response).asObject();
Ray Milkey2b217142014-12-15 09:24:24 -0800841 assertThat(result, matchesIntent(intent));
Ray Milkey05b169d2015-08-13 14:33:33 -0700842
843 // Test get using numeric value
Jian Li9d616492016-03-09 10:52:49 -0800844 final String responseNumeric = wt.path("intents/" + APP_ID.name()
845 + "/0x0").request().get(String.class);
Jian Li80cfe452016-01-14 16:04:58 -0800846 final JsonObject resultNumeric = Json.parse(responseNumeric).asObject();
Ray Milkey05b169d2015-08-13 14:33:33 -0700847 assertThat(resultNumeric, matchesIntent(intent));
Ray Milkey2b217142014-12-15 09:24:24 -0800848 }
849
850 /**
Author Namee252a002016-09-26 22:42:24 +0530851 * Tests the result of a rest api GET for related flows for single intent.
852 */
853 @Test
854 public void testRelatedFlowsForIntents() {
855 List<FlowEntry> flowEntries = new ArrayList<>();
856 flowEntries.add(flow1);
857 flowEntries.add(flow2);
858 List<List<FlowEntry>> paths = new ArrayList<>();
859 paths.add(flowEntries);
860 List<FlowRule> flowRules = new ArrayList<>();
861 flowRules.add(flowRule1);
862 flowRules.add(flowRule2);
863 FlowRuleIntent flowRuleIntent = new FlowRuleIntent(
864 APP_ID,
Ray Milkey39f78b62018-01-05 15:17:37 -0800865 null,
Author Namee252a002016-09-26 22:42:24 +0530866 flowRules,
Ray Milkey39f78b62018-01-05 15:17:37 -0800867 new HashSet<NetworkResource>(),
868 PathIntent.ProtectionType.PRIMARY,
869 null);
Author Namee252a002016-09-26 22:42:24 +0530870 Intent intent = new MockIntent(3L);
871 installableIntents.add(flowRuleIntent);
872 intents.add(intent);
873
874 expect(mockIntentService.getIntent(Key.of(0, APP_ID)))
875 .andReturn(intent)
876 .anyTimes();
877 expect(mockIntentService.getIntent(Key.of("0", APP_ID)))
878 .andReturn(intent)
879 .anyTimes();
880 expect(mockIntentService.getIntent(Key.of(0, APP_ID)))
881 .andReturn(intent)
882 .anyTimes();
883 expect(mockIntentService.getIntent(Key.of("0x0", APP_ID)))
884 .andReturn(null)
885 .anyTimes();
886 expect(mockIntentService.getInstallableIntents(intent.key()))
887 .andReturn(installableIntents)
888 .anyTimes();
889 replay(mockIntentService);
890
891 expect(mockFlowService.getFlowEntries(deviceId1))
892 .andReturn(flowEntries).anyTimes();
893 replay(mockFlowService);
894
895 expect(mockCoreService.getAppId(APP_ID.name()))
896 .andReturn(APP_ID).anyTimes();
897 expect(mockCoreService.getAppId(APP_ID.id()))
898 .andReturn(APP_ID).anyTimes();
899 replay(mockCoreService);
900
901 final WebTarget wt = target();
902
903 // Test get using key string
904 final String response = wt.path("intents/relatedflows/" + APP_ID.name()
905 + "/0").request().get(String.class);
906 final JsonObject result = Json.parse(response).asObject();
907 assertThat(result, matchesRelatedFlowEntries(paths, APP_ID.name()));
908
909 // Test get using numeric value
910 final String responseNumeric = wt.path("intents/relatedflows/" + APP_ID.name()
911 + "/0x0").request().get(String.class);
912 final JsonObject resultNumeric = Json.parse(responseNumeric).asObject();
913 assertThat(resultNumeric, matchesRelatedFlowEntries(paths, APP_ID.name()));
914 }
915
916 /**
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +0200917 * Tests the result of a rest api GET for intent installables.
918 */
919 @Test
920 public void testIntentInstallables() {
921
922 Link link1 = DefaultLink.builder()
923 .type(Link.Type.DIRECT)
924 .providerId(ProviderId.NONE)
925 .src(connectPoint1)
926 .dst(connectPoint2)
927 .build();
928
929 Link link2 = DefaultLink.builder()
930 .type(Link.Type.DIRECT)
931 .providerId(ProviderId.NONE)
932 .src(connectPoint3)
933 .dst(connectPoint4)
934 .build();
935
936 Set<NetworkResource> resources = new HashSet<>();
937 resources.add(link1);
938 resources.add(link2);
939
940 FlowRuleIntent flowRuleIntent = new FlowRuleIntent(
941 APP_ID,
Ray Milkey39f78b62018-01-05 15:17:37 -0800942 null,
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +0200943 new ArrayList<>(),
Ray Milkey39f78b62018-01-05 15:17:37 -0800944 resources,
945 PathIntent.ProtectionType.PRIMARY,
946 null);
Rafal Szaleckif97e0ed2017-06-01 13:07:18 +0200947
948 Intent intent = new MockIntent(MockIntent.nextId());
949 Long intentId = intent.id().id();
950 installableIntents.add(flowRuleIntent);
951 intents.add(intent);
952
953 expect(mockIntentService.getIntent(Key.of(intentId, APP_ID)))
954 .andReturn(intent)
955 .anyTimes();
956 expect(mockIntentService.getIntent(Key.of(intentId.toString(), APP_ID)))
957 .andReturn(intent)
958 .anyTimes();
959 expect(mockIntentService.getIntent(Key.of(intentId, APP_ID)))
960 .andReturn(intent)
961 .anyTimes();
962 expect(mockIntentService.getIntent(Key.of(Long.toHexString(intentId), APP_ID)))
963 .andReturn(null)
964 .anyTimes();
965 expect(mockIntentService.getInstallableIntents(intent.key()))
966 .andReturn(installableIntents)
967 .anyTimes();
968 replay(mockIntentService);
969
970 replay(mockFlowService);
971
972 expect(mockCoreService.getAppId(APP_ID.name()))
973 .andReturn(APP_ID).anyTimes();
974 expect(mockCoreService.getAppId(APP_ID.id()))
975 .andReturn(APP_ID).anyTimes();
976 replay(mockCoreService);
977
978 final WebTarget wt = target();
979
980 // Test get using key string
981 final String response = wt.path("intents/installables/" + APP_ID.name()
982 + "/" + intentId).request().get(String.class);
983 final JsonObject result = Json.parse(response).asObject();
984 assertThat(result.get(INSTALLABLES).asArray(), hasIntent(flowRuleIntent));
985
986 // Test get using numeric value
987 final String responseNumeric = wt.path("intents/installables/" + APP_ID.name()
988 + "/" + Long.toHexString(intentId)).request().get(String.class);
989 final JsonObject resultNumeric = Json.parse(responseNumeric).asObject();
990 assertThat(resultNumeric.get(INSTALLABLES).asArray(), hasIntent(flowRuleIntent));
991 }
992
993 /**
Ray Milkey2b217142014-12-15 09:24:24 -0800994 * Tests that a fetch of a non-existent intent object throws an exception.
995 */
996 @Test
997 public void testBadGet() {
998
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800999 expect(mockIntentService.getIntent(Key.of(0, APP_ID)))
Ray Milkey2b217142014-12-15 09:24:24 -08001000 .andReturn(null)
1001 .anyTimes();
1002 replay(mockIntentService);
1003
Jian Li9d616492016-03-09 10:52:49 -08001004 WebTarget wt = target();
Ray Milkey2b217142014-12-15 09:24:24 -08001005 try {
Jian Li9d616492016-03-09 10:52:49 -08001006 wt.path("intents/0").request().get(String.class);
Ray Milkey2b217142014-12-15 09:24:24 -08001007 fail("Fetch of non-existent intent did not throw an exception");
Jian Li9d616492016-03-09 10:52:49 -08001008 } catch (NotFoundException ex) {
Ray Milkey2b217142014-12-15 09:24:24 -08001009 assertThat(ex.getMessage(),
Jian Li9d616492016-03-09 10:52:49 -08001010 containsString("HTTP 404 Not Found"));
Ray Milkey2b217142014-12-15 09:24:24 -08001011 }
1012 }
Ray Milkeyb82c42b2015-06-30 09:42:20 -07001013
1014 /**
1015 * Tests creating an intent with POST.
1016 */
1017 @Test
1018 public void testPost() {
Ray Milkeyf7cb4012015-07-20 13:01:07 -07001019 ApplicationId testId = new DefaultApplicationId(2, "myApp");
1020 expect(mockCoreService.getAppId("myApp"))
1021 .andReturn(testId);
Ray Milkeyb82c42b2015-06-30 09:42:20 -07001022 replay(mockCoreService);
1023
1024 mockIntentService.submit(anyObject());
1025 expectLastCall();
1026 replay(mockIntentService);
1027
1028 InputStream jsonStream = IntentsResourceTest.class
1029 .getResourceAsStream("post-intent.json");
Jian Li9d616492016-03-09 10:52:49 -08001030 WebTarget wt = target();
Ray Milkeyb82c42b2015-06-30 09:42:20 -07001031
Jian Li9d616492016-03-09 10:52:49 -08001032 Response response = wt.path("intents")
1033 .request(MediaType.APPLICATION_JSON_TYPE)
1034 .post(Entity.json(jsonStream));
Ray Milkeyb82c42b2015-06-30 09:42:20 -07001035 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
1036 String location = response.getLocation().getPath();
Ray Milkey8d076402015-08-31 15:43:18 -07001037 assertThat(location, Matchers.startsWith("/intents/myApp/"));
Ray Milkeyb82c42b2015-06-30 09:42:20 -07001038 }
Ray Milkey7b158512015-07-21 16:32:43 -07001039
1040 /**
Ray Milkey05b169d2015-08-13 14:33:33 -07001041 * Tests creating an intent with POST and illegal JSON.
1042 */
1043 @Test
1044 public void testBadPost() {
1045 replay(mockCoreService);
1046 replay(mockIntentService);
1047
1048 String json = "this is invalid!";
Jian Li9d616492016-03-09 10:52:49 -08001049 WebTarget wt = target();
Ray Milkey05b169d2015-08-13 14:33:33 -07001050
Jian Li9d616492016-03-09 10:52:49 -08001051 Response response = wt.path("intents")
1052 .request(MediaType.APPLICATION_JSON_TYPE)
1053 .post(Entity.json(json));
Ray Milkey05b169d2015-08-13 14:33:33 -07001054 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_BAD_REQUEST));
1055 }
1056
1057 /**
Ray Milkey7b158512015-07-21 16:32:43 -07001058 * Tests removing an intent with DELETE.
1059 */
1060 @Test
1061 public void testRemove() {
1062 final HashSet<NetworkResource> resources = new HashSet<>();
1063 resources.add(new MockResource(1));
1064 resources.add(new MockResource(2));
1065 resources.add(new MockResource(3));
1066 final Intent intent = new MockIntent(3L, resources);
1067 final ApplicationId appId = new DefaultApplicationId(2, "app");
1068 IntentService fakeManager = new FakeIntentManager();
1069
1070 expect(mockCoreService.getAppId("app"))
1071 .andReturn(appId).once();
1072 replay(mockCoreService);
1073
1074 mockIntentService.withdraw(anyObject());
1075 expectLastCall().andDelegateTo(fakeManager).once();
1076 expect(mockIntentService.getIntent(Key.of(2, appId)))
1077 .andReturn(intent)
1078 .once();
1079 expect(mockIntentService.getIntent(Key.of("0x2", appId)))
1080 .andReturn(null)
1081 .once();
1082
1083 mockIntentService.addListener(anyObject());
1084 expectLastCall().andDelegateTo(fakeManager).once();
1085 mockIntentService.removeListener(anyObject());
1086 expectLastCall().andDelegateTo(fakeManager).once();
1087
1088 replay(mockIntentService);
1089
Jian Li9d616492016-03-09 10:52:49 -08001090 WebTarget wt = target();
Ray Milkey7b158512015-07-21 16:32:43 -07001091
Jian Li9d616492016-03-09 10:52:49 -08001092 Response response = wt.path("intents/app/0x2")
Ray Milkey7c251822016-04-06 17:38:25 -07001093 .request(MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN)
Jian Li9d616492016-03-09 10:52:49 -08001094 .delete();
Ray Milkey7b158512015-07-21 16:32:43 -07001095 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NO_CONTENT));
1096 }
Ray Milkey05b169d2015-08-13 14:33:33 -07001097
1098 /**
1099 * Tests removal of a non existent intent with DELETE.
1100 */
1101 @Test
1102 public void testBadRemove() {
1103 final ApplicationId appId = new DefaultApplicationId(2, "app");
1104
1105 expect(mockCoreService.getAppId("app"))
1106 .andReturn(appId).once();
1107 replay(mockCoreService);
1108
1109 expect(mockIntentService.getIntent(Key.of(2, appId)))
1110 .andReturn(null)
1111 .once();
1112 expect(mockIntentService.getIntent(Key.of("0x2", appId)))
1113 .andReturn(null)
1114 .once();
1115
1116 replay(mockIntentService);
1117
Jian Li9d616492016-03-09 10:52:49 -08001118 WebTarget wt = target();
Ray Milkey05b169d2015-08-13 14:33:33 -07001119
Jian Li9d616492016-03-09 10:52:49 -08001120 Response response = wt.path("intents/app/0x2")
Ray Milkey7c251822016-04-06 17:38:25 -07001121 .request(MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN)
Jian Li9d616492016-03-09 10:52:49 -08001122 .delete();
Ray Milkey05b169d2015-08-13 14:33:33 -07001123 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NO_CONTENT));
1124 }
1125
dvaddire95c84ed2017-06-14 15:42:24 +05301126 @Test
1127 public void testIntentsMiniSummary() {
1128 final Intent intent1 = new MockIntent(1L, Collections.emptyList());
1129 final HashSet<NetworkResource> resources = new HashSet<>();
1130 resources.add(new MockResource(1));
1131 resources.add(new MockResource(2));
1132 resources.add(new MockResource(3));
1133 final Intent intent2 = new MockIntent(2L, resources);
1134 intents.add(intent1);
1135 intents.add(intent2);
1136 final WebTarget wt = target();
1137 replay(mockIntentService);
1138 final String response = wt.path("intents/minisummary").request().get(String.class);
1139 assertThat(response, containsString("{\"All\":{"));
1140 final JsonObject result = Json.parse(response).asObject();
1141 assertThat(result, notNullValue());
1142 assertThat(result.names(), hasSize(2));
1143 assertThat(result.names().get(0), containsString("All"));
1144 JsonObject jsonIntents = (JsonObject) result.get("All");
1145 assertThat(jsonIntents, notNullValue());
1146 assertThat(jsonIntents.get("total").toString(), containsString("2"));
1147 jsonIntents = (JsonObject) result.get("Mock");
1148 assertThat(jsonIntents, notNullValue());
1149 assertThat(jsonIntents.get("installed").toString(), containsString("2"));
1150 }
Ray Milkey2b217142014-12-15 09:24:24 -08001151}
dvaddire95c84ed2017-06-14 15:42:24 +05301152