blob: 7a2ce151ecede10cca13e54e49132185ad0742e6 [file] [log] [blame]
Ray Milkey2b217142014-12-15 09:24:24 -08001/*
2 * Copyright 2014 Open Networking Laboratory
3 *
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
18import java.util.Collection;
Sho SHIMIZUd7d18002015-01-21 14:37:14 -080019import java.util.Collections;
Ray Milkey2b217142014-12-15 09:24:24 -080020import java.util.HashSet;
21import java.util.concurrent.atomic.AtomicLong;
22
23import org.hamcrest.Description;
24import org.hamcrest.TypeSafeMatcher;
25import org.junit.After;
26import org.junit.Before;
Jonathan Hart4fd4ebb2015-02-04 17:38:48 -080027import org.junit.Ignore;
Ray Milkey2b217142014-12-15 09:24:24 -080028import org.junit.Test;
29import org.onlab.osgi.ServiceDirectory;
30import org.onlab.osgi.TestServiceDirectory;
31import org.onlab.rest.BaseResource;
32import org.onosproject.codec.CodecService;
33import org.onosproject.codec.impl.CodecManager;
34import org.onosproject.core.ApplicationId;
Ayaka Koshibec06c89b2015-02-10 19:25:41 -080035import org.onosproject.core.CoreService;
Ray Milkey2b217142014-12-15 09:24:24 -080036import org.onosproject.core.DefaultApplicationId;
37import org.onosproject.core.IdGenerator;
38import org.onosproject.net.NetworkResource;
39import org.onosproject.net.intent.Intent;
Ray Milkey2b217142014-12-15 09:24:24 -080040import org.onosproject.net.intent.IntentService;
Ray Milkeyf9af43c2015-02-09 16:45:48 -080041import org.onosproject.net.intent.Key;
Ray Milkey2b217142014-12-15 09:24:24 -080042
43import com.eclipsesource.json.JsonArray;
44import com.eclipsesource.json.JsonObject;
45import com.eclipsesource.json.JsonValue;
46import com.google.common.base.MoreObjects;
47import com.sun.jersey.api.client.UniformInterfaceException;
48import com.sun.jersey.api.client.WebResource;
Ray Milkey2b217142014-12-15 09:24:24 -080049
50import static org.easymock.EasyMock.createMock;
51import static org.easymock.EasyMock.expect;
52import static org.easymock.EasyMock.replay;
53import static org.easymock.EasyMock.verify;
54import static org.hamcrest.Matchers.containsString;
55import static org.hamcrest.Matchers.hasSize;
56import static org.hamcrest.Matchers.is;
57import static org.hamcrest.Matchers.notNullValue;
58import static org.junit.Assert.assertThat;
59import static org.junit.Assert.fail;
60
61/**
62 * Unit tests for Intents REST APIs.
63 */
Jonathan Hart4fd4ebb2015-02-04 17:38:48 -080064@Ignore
Ray Milkey9c3d3362015-01-28 10:39:56 -080065public class IntentsResourceTest extends ResourceTest {
Ray Milkey2b217142014-12-15 09:24:24 -080066 final IntentService mockIntentService = createMock(IntentService.class);
Ayaka Koshibec06c89b2015-02-10 19:25:41 -080067 final CoreService mockCoreService = createMock(CoreService.class);
Ray Milkey2b217142014-12-15 09:24:24 -080068 final HashSet<Intent> intents = new HashSet<>();
Thomas Vachuska02aeb032015-01-06 22:36:30 -080069 private static final ApplicationId APP_ID = new DefaultApplicationId(1, "test");
Ray Milkey2b217142014-12-15 09:24:24 -080070 private IdGenerator mockGenerator;
71
72 /**
73 * Mock ID generator. This should be refactored to share the one in
74 * the core/api tests.
75 */
76 public class MockIdGenerator implements IdGenerator {
77 private AtomicLong nextId = new AtomicLong(0);
78
79 @Override
80 public long getNewId() {
81 return nextId.getAndIncrement();
82 }
83 }
84
85 /**
86 * Mock compilable intent class.
87 */
88 private static class MockIntent extends Intent {
89
90 public MockIntent(Collection<NetworkResource> resources) {
91 super(APP_ID, resources);
92 }
93
94 @Override
95 public String toString() {
96 return MoreObjects.toStringHelper(getClass())
97 .add("id", id())
98 .add("appId", appId())
99 .toString();
100 }
101 }
102
103 private class MockResource implements NetworkResource {
104 int id;
105
106 MockResource(int id) {
107 this.id = id;
108 }
109
Ayaka Koshibec06c89b2015-02-10 19:25:41 -0800110 @Override
Ray Milkey2b217142014-12-15 09:24:24 -0800111 public String toString() {
112 return "Resource " + Integer.toString(id);
113 }
114 }
115
Ray Milkey2b217142014-12-15 09:24:24 -0800116 /**
117 * Hamcrest matcher to check that an intent representation in JSON matches
118 * the actual intent.
119 */
120 public static class IntentJsonMatcher extends TypeSafeMatcher<JsonObject> {
121 private final Intent intent;
122 private String reason = "";
123
124 public IntentJsonMatcher(Intent intentValue) {
125 intent = intentValue;
126 }
127
128 @Override
129 public boolean matchesSafely(JsonObject jsonIntent) {
130 // check id
131 final String jsonId = jsonIntent.get("id").asString();
132 if (!jsonId.equals(intent.id().toString())) {
133 reason = "id " + intent.id().toString();
134 return false;
135 }
136
137 // check application id
138 final String jsonAppId = jsonIntent.get("appId").asString();
139 if (!jsonAppId.equals(intent.appId().toString())) {
140 reason = "appId " + intent.appId().toString();
141 return false;
142 }
143
144 // check intent type
145 final String jsonType = jsonIntent.get("type").asString();
146 if (!jsonType.equals("MockIntent")) {
147 reason = "type MockIntent";
148 return false;
149 }
150
151 // check details field
152 final String jsonDetails = jsonIntent.get("details").asString();
153 if (!jsonDetails.equals(intent.toString())) {
154 reason = "details " + intent.toString();
155 return false;
156 }
157
158 // check resources array
159 final JsonArray jsonResources = jsonIntent.get("resources").asArray();
160 if (intent.resources() != null) {
161 if (intent.resources().size() != jsonResources.size()) {
162 reason = "resources array size of " + Integer.toString(intent.resources().size());
163 return false;
164 }
165 for (final NetworkResource resource : intent.resources()) {
166 boolean resourceFound = false;
167 final String resourceString = resource.toString();
168 for (int resourceIndex = 0; resourceIndex < jsonResources.size(); resourceIndex++) {
169 final JsonValue value = jsonResources.get(resourceIndex);
170 if (value.asString().equals(resourceString)) {
171 resourceFound = true;
172 }
173 }
174 if (!resourceFound) {
175 reason = "resource " + resourceString;
176 return false;
177 }
178 }
179 } else if (jsonResources.size() != 0) {
180 reason = "resources array empty";
181 return false;
182 }
183 return true;
184 }
185
186 @Override
187 public void describeTo(Description description) {
188 description.appendText(reason);
189 }
190 }
191
192 /**
193 * Factory to allocate an intent matcher.
194 *
195 * @param intent intent object we are looking for
196 * @return matcher
197 */
198 private static IntentJsonMatcher matchesIntent(Intent intent) {
199 return new IntentJsonMatcher(intent);
200 }
201
202 /**
203 * Hamcrest matcher to check that an intent is represented properly in a JSON
204 * array of intents.
205 */
206 public static class IntentJsonArrayMatcher extends TypeSafeMatcher<JsonArray> {
207 private final Intent intent;
208 private String reason = "";
209
210 public IntentJsonArrayMatcher(Intent intentValue) {
211 intent = intentValue;
212 }
213
214 @Override
215 public boolean matchesSafely(JsonArray json) {
216 boolean intentFound = false;
217 final int expectedAttributes = 5;
218 for (int jsonIntentIndex = 0; jsonIntentIndex < json.size();
219 jsonIntentIndex++) {
220
221 final JsonObject jsonIntent = json.get(jsonIntentIndex).asObject();
222
223 if (jsonIntent.names().size() != expectedAttributes) {
224 reason = "Found an intent with the wrong number of attributes";
225 return false;
226 }
227
228 final String jsonIntentId = jsonIntent.get("id").asString();
229 if (jsonIntentId.equals(intent.id().toString())) {
230 intentFound = true;
231
232 // We found the correct intent, check attribute values
233 assertThat(jsonIntent, matchesIntent(intent));
234 }
235 }
236 if (!intentFound) {
237 reason = "Intent with id " + intent.id().toString() + " not found";
238 return false;
239 } else {
240 return true;
241 }
242 }
243
244 @Override
245 public void describeTo(Description description) {
246 description.appendText(reason);
247 }
248 }
249
250 /**
251 * Factory to allocate an intent array matcher.
252 *
253 * @param intent intent object we are looking for
254 * @return matcher
255 */
256 private static IntentJsonArrayMatcher hasIntent(Intent intent) {
257 return new IntentJsonArrayMatcher(intent);
258 }
Ray Milkey4f5de002014-12-17 19:26:11 -0800259
Ray Milkeyed0b1662015-02-05 09:34:29 -0800260 /**
261 * Initializes test mocks and environment.
262 */
Ray Milkey2b217142014-12-15 09:24:24 -0800263 @Before
Ray Milkeyed0b1662015-02-05 09:34:29 -0800264 public void setUpTest() {
Ray Milkey2b217142014-12-15 09:24:24 -0800265 expect(mockIntentService.getIntents()).andReturn(intents).anyTimes();
Ray Milkey2b217142014-12-15 09:24:24 -0800266 // Register the services needed for the test
267 final CodecManager codecService = new CodecManager();
268 codecService.activate();
269 ServiceDirectory testDirectory =
270 new TestServiceDirectory()
271 .add(IntentService.class, mockIntentService)
Ayaka Koshibec06c89b2015-02-10 19:25:41 -0800272 .add(CodecService.class, codecService)
273 .add(CoreService.class, mockCoreService);
Ray Milkey2b217142014-12-15 09:24:24 -0800274
275 BaseResource.setServiceDirectory(testDirectory);
276
277 mockGenerator = new MockIdGenerator();
278 Intent.bindIdGenerator(mockGenerator);
279 }
280
Ray Milkeyed0b1662015-02-05 09:34:29 -0800281 /**
282 * Tears down and verifies test mocks and environment.
283 */
Ray Milkey2b217142014-12-15 09:24:24 -0800284 @After
Ray Milkeyed0b1662015-02-05 09:34:29 -0800285 public void tearDownTest() {
Ray Milkey2b217142014-12-15 09:24:24 -0800286 verify(mockIntentService);
287 Intent.unbindIdGenerator(mockGenerator);
288 }
289
290 /**
291 * Tests the result of the rest api GET when there are no intents.
292 */
293 @Test
294 public void testIntentsEmptyArray() {
295 replay(mockIntentService);
296 final WebResource rs = resource();
297 final String response = rs.path("intents").get(String.class);
298 assertThat(response, is("{\"intents\":[]}"));
299 }
300
301 /**
302 * Tests the result of the rest api GET when intents are defined.
303 */
304 @Test
305 public void testIntentsArray() {
306 replay(mockIntentService);
307
Sho SHIMIZUd7d18002015-01-21 14:37:14 -0800308 final Intent intent1 = new MockIntent(Collections.emptyList());
Ray Milkey2b217142014-12-15 09:24:24 -0800309 final HashSet<NetworkResource> resources = new HashSet<>();
310 resources.add(new MockResource(1));
311 resources.add(new MockResource(2));
312 resources.add(new MockResource(3));
313 final Intent intent2 = new MockIntent(resources);
314
315 intents.add(intent1);
316 intents.add(intent2);
317 final WebResource rs = resource();
318 final String response = rs.path("intents").get(String.class);
319 assertThat(response, containsString("{\"intents\":["));
320
321 final JsonObject result = JsonObject.readFrom(response);
322 assertThat(result, notNullValue());
323
324 assertThat(result.names(), hasSize(1));
325 assertThat(result.names().get(0), is("intents"));
326
327 final JsonArray jsonIntents = result.get("intents").asArray();
328 assertThat(jsonIntents, notNullValue());
329
330 assertThat(jsonIntents, hasIntent(intent1));
331 assertThat(jsonIntents, hasIntent(intent2));
332 }
333
334 /**
335 * Tests the result of a rest api GET for a single intent.
336 */
337 @Test
338 public void testIntentsSingle() {
339 final HashSet<NetworkResource> resources = new HashSet<>();
340 resources.add(new MockResource(1));
341 resources.add(new MockResource(2));
342 resources.add(new MockResource(3));
343 final Intent intent = new MockIntent(resources);
344
345 intents.add(intent);
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(intent)
349 .anyTimes();
Ayaka Koshibec06c89b2015-02-10 19:25:41 -0800350 expect(mockIntentService.getIntent(Key.of("0", APP_ID)))
351 .andReturn(intent)
352 .anyTimes();
Ray Milkey2b217142014-12-15 09:24:24 -0800353 replay(mockIntentService);
Ayaka Koshibec06c89b2015-02-10 19:25:41 -0800354 expect(mockCoreService.getAppId(APP_ID.id()))
355 .andReturn(APP_ID).anyTimes();
356 replay(mockCoreService);
Ray Milkey2b217142014-12-15 09:24:24 -0800357 final WebResource rs = resource();
Ayaka Koshibec06c89b2015-02-10 19:25:41 -0800358 final String response = rs.path("intents/1/0").get(String.class);
Ray Milkey2b217142014-12-15 09:24:24 -0800359 final JsonObject result = JsonObject.readFrom(response);
360 assertThat(result, matchesIntent(intent));
361 }
362
363 /**
364 * Tests that a fetch of a non-existent intent object throws an exception.
365 */
366 @Test
367 public void testBadGet() {
368
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800369 expect(mockIntentService.getIntent(Key.of(0, APP_ID)))
Ray Milkey2b217142014-12-15 09:24:24 -0800370 .andReturn(null)
371 .anyTimes();
372 replay(mockIntentService);
373
374 WebResource rs = resource();
375 try {
376 rs.path("intents/0").get(String.class);
377 fail("Fetch of non-existent intent did not throw an exception");
378 } catch (UniformInterfaceException ex) {
379 assertThat(ex.getMessage(),
380 containsString("returned a response status of"));
381 }
382 }
383}