blob: 08a6ce595ba338d938ff0057d9de4e6703a62afc [file] [log] [blame]
Ray Milkey2b217142014-12-15 09:24:24 -08001/*
Ray Milkey34c95902015-04-15 09:47:53 -07002 * Copyright 2014-2015 Open Networking Laboratory
Ray Milkey2b217142014-12-15 09:24:24 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.rest;
17
Sho SHIMIZUd7d18002015-01-21 14:37:14 -080018import java.util.Collections;
Ray Milkey2b217142014-12-15 09:24:24 -080019import java.util.HashSet;
Ray Milkey2b217142014-12-15 09:24:24 -080020
21import org.hamcrest.Description;
22import org.hamcrest.TypeSafeMatcher;
23import org.junit.After;
24import org.junit.Before;
25import org.junit.Test;
26import org.onlab.osgi.ServiceDirectory;
27import org.onlab.osgi.TestServiceDirectory;
28import org.onlab.rest.BaseResource;
29import org.onosproject.codec.CodecService;
30import org.onosproject.codec.impl.CodecManager;
31import org.onosproject.core.ApplicationId;
Ayaka Koshibec06c89b2015-02-10 19:25:41 -080032import org.onosproject.core.CoreService;
Ray Milkey2b217142014-12-15 09:24:24 -080033import org.onosproject.core.DefaultApplicationId;
34import org.onosproject.core.IdGenerator;
35import org.onosproject.net.NetworkResource;
36import org.onosproject.net.intent.Intent;
Ray Milkey2b217142014-12-15 09:24:24 -080037import org.onosproject.net.intent.IntentService;
Ray Milkey1534f8d2015-05-13 15:42:50 -070038import org.onosproject.net.intent.IntentState;
Ray Milkeyf9af43c2015-02-09 16:45:48 -080039import org.onosproject.net.intent.Key;
Ray Milkey43a28222015-02-23 13:57:58 -080040import org.onosproject.net.intent.MockIdGenerator;
Ray Milkey2b217142014-12-15 09:24:24 -080041
42import com.eclipsesource.json.JsonArray;
43import com.eclipsesource.json.JsonObject;
44import com.eclipsesource.json.JsonValue;
Ray Milkey2b217142014-12-15 09:24:24 -080045import com.sun.jersey.api.client.UniformInterfaceException;
46import com.sun.jersey.api.client.WebResource;
Ray Milkey2b217142014-12-15 09:24:24 -080047
Ray Milkey1534f8d2015-05-13 15:42:50 -070048import static org.easymock.EasyMock.anyObject;
Ray Milkey2b217142014-12-15 09:24:24 -080049import static org.easymock.EasyMock.createMock;
50import static org.easymock.EasyMock.expect;
51import static org.easymock.EasyMock.replay;
52import static org.easymock.EasyMock.verify;
53import static org.hamcrest.Matchers.containsString;
54import static org.hamcrest.Matchers.hasSize;
55import static org.hamcrest.Matchers.is;
56import static org.hamcrest.Matchers.notNullValue;
57import static org.junit.Assert.assertThat;
58import static org.junit.Assert.fail;
Ray Milkey43a28222015-02-23 13:57:58 -080059import static org.onosproject.net.intent.IntentTestsMocks.MockIntent;
Ray Milkey2b217142014-12-15 09:24:24 -080060
61/**
62 * Unit tests for Intents REST APIs.
63 */
Ray Milkey9c3d3362015-01-28 10:39:56 -080064public class IntentsResourceTest extends ResourceTest {
Ray Milkey2b217142014-12-15 09:24:24 -080065 final IntentService mockIntentService = createMock(IntentService.class);
Ayaka Koshibec06c89b2015-02-10 19:25:41 -080066 final CoreService mockCoreService = createMock(CoreService.class);
Ray Milkey2b217142014-12-15 09:24:24 -080067 final HashSet<Intent> intents = new HashSet<>();
Thomas Vachuska02aeb032015-01-06 22:36:30 -080068 private static final ApplicationId APP_ID = new DefaultApplicationId(1, "test");
Ray Milkey2b217142014-12-15 09:24:24 -080069 private IdGenerator mockGenerator;
70
Ray Milkey2b217142014-12-15 09:24:24 -080071 private class MockResource implements NetworkResource {
72 int id;
73
74 MockResource(int id) {
75 this.id = id;
76 }
77
Ayaka Koshibec06c89b2015-02-10 19:25:41 -080078 @Override
Ray Milkey2b217142014-12-15 09:24:24 -080079 public String toString() {
80 return "Resource " + Integer.toString(id);
81 }
82 }
83
Ray Milkey2b217142014-12-15 09:24:24 -080084 /**
85 * Hamcrest matcher to check that an intent representation in JSON matches
86 * the actual intent.
87 */
88 public static class IntentJsonMatcher extends TypeSafeMatcher<JsonObject> {
89 private final Intent intent;
90 private String reason = "";
91
92 public IntentJsonMatcher(Intent intentValue) {
93 intent = intentValue;
94 }
95
96 @Override
97 public boolean matchesSafely(JsonObject jsonIntent) {
98 // check id
99 final String jsonId = jsonIntent.get("id").asString();
100 if (!jsonId.equals(intent.id().toString())) {
101 reason = "id " + intent.id().toString();
102 return false;
103 }
104
105 // check application id
106 final String jsonAppId = jsonIntent.get("appId").asString();
107 if (!jsonAppId.equals(intent.appId().toString())) {
108 reason = "appId " + intent.appId().toString();
109 return false;
110 }
111
112 // check intent type
113 final String jsonType = jsonIntent.get("type").asString();
114 if (!jsonType.equals("MockIntent")) {
115 reason = "type MockIntent";
116 return false;
117 }
118
119 // check details field
120 final String jsonDetails = jsonIntent.get("details").asString();
121 if (!jsonDetails.equals(intent.toString())) {
122 reason = "details " + intent.toString();
123 return false;
124 }
125
Ray Milkey1534f8d2015-05-13 15:42:50 -0700126 // check state field
127 final String jsonState = jsonIntent.get("state").asString();
128 if (!jsonState.equals("INSTALLED")) {
129 reason = "state INSTALLED";
130 return false;
131 }
132
Ray Milkey2b217142014-12-15 09:24:24 -0800133 // check resources array
134 final JsonArray jsonResources = jsonIntent.get("resources").asArray();
135 if (intent.resources() != null) {
136 if (intent.resources().size() != jsonResources.size()) {
137 reason = "resources array size of " + Integer.toString(intent.resources().size());
138 return false;
139 }
140 for (final NetworkResource resource : intent.resources()) {
141 boolean resourceFound = false;
142 final String resourceString = resource.toString();
143 for (int resourceIndex = 0; resourceIndex < jsonResources.size(); resourceIndex++) {
144 final JsonValue value = jsonResources.get(resourceIndex);
145 if (value.asString().equals(resourceString)) {
146 resourceFound = true;
147 }
148 }
149 if (!resourceFound) {
150 reason = "resource " + resourceString;
151 return false;
152 }
153 }
154 } else if (jsonResources.size() != 0) {
155 reason = "resources array empty";
156 return false;
157 }
158 return true;
159 }
160
161 @Override
162 public void describeTo(Description description) {
163 description.appendText(reason);
164 }
165 }
166
167 /**
168 * Factory to allocate an intent matcher.
169 *
170 * @param intent intent object we are looking for
171 * @return matcher
172 */
173 private static IntentJsonMatcher matchesIntent(Intent intent) {
174 return new IntentJsonMatcher(intent);
175 }
176
177 /**
178 * Hamcrest matcher to check that an intent is represented properly in a JSON
179 * array of intents.
180 */
181 public static class IntentJsonArrayMatcher extends TypeSafeMatcher<JsonArray> {
182 private final Intent intent;
183 private String reason = "";
184
185 public IntentJsonArrayMatcher(Intent intentValue) {
186 intent = intentValue;
187 }
188
189 @Override
190 public boolean matchesSafely(JsonArray json) {
191 boolean intentFound = false;
Ray Milkey1534f8d2015-05-13 15:42:50 -0700192 final int expectedAttributes = 6;
Ray Milkey2b217142014-12-15 09:24:24 -0800193 for (int jsonIntentIndex = 0; jsonIntentIndex < json.size();
194 jsonIntentIndex++) {
195
196 final JsonObject jsonIntent = json.get(jsonIntentIndex).asObject();
197
198 if (jsonIntent.names().size() != expectedAttributes) {
199 reason = "Found an intent with the wrong number of attributes";
200 return false;
201 }
202
203 final String jsonIntentId = jsonIntent.get("id").asString();
204 if (jsonIntentId.equals(intent.id().toString())) {
205 intentFound = true;
206
207 // We found the correct intent, check attribute values
208 assertThat(jsonIntent, matchesIntent(intent));
209 }
210 }
211 if (!intentFound) {
212 reason = "Intent with id " + intent.id().toString() + " not found";
213 return false;
214 } else {
215 return true;
216 }
217 }
218
219 @Override
220 public void describeTo(Description description) {
221 description.appendText(reason);
222 }
223 }
224
225 /**
226 * Factory to allocate an intent array matcher.
227 *
228 * @param intent intent object we are looking for
229 * @return matcher
230 */
231 private static IntentJsonArrayMatcher hasIntent(Intent intent) {
232 return new IntentJsonArrayMatcher(intent);
233 }
Ray Milkey4f5de002014-12-17 19:26:11 -0800234
Ray Milkeyed0b1662015-02-05 09:34:29 -0800235 /**
236 * Initializes test mocks and environment.
237 */
Ray Milkey2b217142014-12-15 09:24:24 -0800238 @Before
Ray Milkeyed0b1662015-02-05 09:34:29 -0800239 public void setUpTest() {
Ray Milkey2b217142014-12-15 09:24:24 -0800240 expect(mockIntentService.getIntents()).andReturn(intents).anyTimes();
Ray Milkey1534f8d2015-05-13 15:42:50 -0700241 expect(mockIntentService.getIntentState(anyObject()))
242 .andReturn(IntentState.INSTALLED)
243 .anyTimes();
Ray Milkey2b217142014-12-15 09:24:24 -0800244 // Register the services needed for the test
245 final CodecManager codecService = new CodecManager();
246 codecService.activate();
247 ServiceDirectory testDirectory =
248 new TestServiceDirectory()
249 .add(IntentService.class, mockIntentService)
Ayaka Koshibec06c89b2015-02-10 19:25:41 -0800250 .add(CodecService.class, codecService)
251 .add(CoreService.class, mockCoreService);
Ray Milkey2b217142014-12-15 09:24:24 -0800252
253 BaseResource.setServiceDirectory(testDirectory);
254
255 mockGenerator = new MockIdGenerator();
256 Intent.bindIdGenerator(mockGenerator);
257 }
258
Ray Milkeyed0b1662015-02-05 09:34:29 -0800259 /**
260 * Tears down and verifies test mocks and environment.
261 */
Ray Milkey2b217142014-12-15 09:24:24 -0800262 @After
Ray Milkeyed0b1662015-02-05 09:34:29 -0800263 public void tearDownTest() {
Ray Milkey2b217142014-12-15 09:24:24 -0800264 verify(mockIntentService);
265 Intent.unbindIdGenerator(mockGenerator);
266 }
267
268 /**
269 * Tests the result of the rest api GET when there are no intents.
270 */
271 @Test
272 public void testIntentsEmptyArray() {
273 replay(mockIntentService);
274 final WebResource rs = resource();
275 final String response = rs.path("intents").get(String.class);
276 assertThat(response, is("{\"intents\":[]}"));
277 }
278
279 /**
280 * Tests the result of the rest api GET when intents are defined.
281 */
282 @Test
283 public void testIntentsArray() {
284 replay(mockIntentService);
285
Ray Milkey43a28222015-02-23 13:57:58 -0800286 final Intent intent1 = new MockIntent(1L, Collections.emptyList());
Ray Milkey2b217142014-12-15 09:24:24 -0800287 final HashSet<NetworkResource> resources = new HashSet<>();
288 resources.add(new MockResource(1));
289 resources.add(new MockResource(2));
290 resources.add(new MockResource(3));
Ray Milkey43a28222015-02-23 13:57:58 -0800291 final Intent intent2 = new MockIntent(2L, resources);
Ray Milkey2b217142014-12-15 09:24:24 -0800292
293 intents.add(intent1);
294 intents.add(intent2);
295 final WebResource rs = resource();
296 final String response = rs.path("intents").get(String.class);
297 assertThat(response, containsString("{\"intents\":["));
298
299 final JsonObject result = JsonObject.readFrom(response);
300 assertThat(result, notNullValue());
301
302 assertThat(result.names(), hasSize(1));
303 assertThat(result.names().get(0), is("intents"));
304
305 final JsonArray jsonIntents = result.get("intents").asArray();
306 assertThat(jsonIntents, notNullValue());
307
308 assertThat(jsonIntents, hasIntent(intent1));
309 assertThat(jsonIntents, hasIntent(intent2));
310 }
311
312 /**
313 * Tests the result of a rest api GET for a single intent.
314 */
315 @Test
316 public void testIntentsSingle() {
317 final HashSet<NetworkResource> resources = new HashSet<>();
318 resources.add(new MockResource(1));
319 resources.add(new MockResource(2));
320 resources.add(new MockResource(3));
Ray Milkey43a28222015-02-23 13:57:58 -0800321 final Intent intent = new MockIntent(3L, resources);
Ray Milkey2b217142014-12-15 09:24:24 -0800322
323 intents.add(intent);
324
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800325 expect(mockIntentService.getIntent(Key.of(0, APP_ID)))
Ray Milkey2b217142014-12-15 09:24:24 -0800326 .andReturn(intent)
327 .anyTimes();
Ayaka Koshibec06c89b2015-02-10 19:25:41 -0800328 expect(mockIntentService.getIntent(Key.of("0", APP_ID)))
329 .andReturn(intent)
330 .anyTimes();
Ray Milkey2b217142014-12-15 09:24:24 -0800331 replay(mockIntentService);
Ayaka Koshibec06c89b2015-02-10 19:25:41 -0800332 expect(mockCoreService.getAppId(APP_ID.id()))
333 .andReturn(APP_ID).anyTimes();
334 replay(mockCoreService);
Ray Milkey2b217142014-12-15 09:24:24 -0800335 final WebResource rs = resource();
Ayaka Koshibec06c89b2015-02-10 19:25:41 -0800336 final String response = rs.path("intents/1/0").get(String.class);
Ray Milkey2b217142014-12-15 09:24:24 -0800337 final JsonObject result = JsonObject.readFrom(response);
338 assertThat(result, matchesIntent(intent));
339 }
340
341 /**
342 * Tests that a fetch of a non-existent intent object throws an exception.
343 */
344 @Test
345 public void testBadGet() {
346
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800347 expect(mockIntentService.getIntent(Key.of(0, APP_ID)))
Ray Milkey2b217142014-12-15 09:24:24 -0800348 .andReturn(null)
349 .anyTimes();
350 replay(mockIntentService);
351
352 WebResource rs = resource();
353 try {
354 rs.path("intents/0").get(String.class);
355 fail("Fetch of non-existent intent did not throw an exception");
356 } catch (UniformInterfaceException ex) {
357 assertThat(ex.getMessage(),
358 containsString("returned a response status of"));
359 }
360 }
361}