blob: 85b7452e0785798350130785adbf7b5c4112eb5f [file] [log] [blame]
Ray Milkey1f95bd32014-12-10 11:11:00 -08001/*
Ray Milkey34c95902015-04-15 09:47:53 -07002 * Copyright 2014-2015 Open Networking Laboratory
Ray Milkey1f95bd32014-12-10 11:11:00 -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
18
Jian Li80cfe452016-01-14 16:04:58 -080019import com.eclipsesource.json.Json;
Jian Li9d616492016-03-09 10:52:49 -080020import com.eclipsesource.json.JsonArray;
21import com.eclipsesource.json.JsonObject;
22import com.google.common.collect.ImmutableSet;
Ray Milkey1f95bd32014-12-10 11:11:00 -080023import org.hamcrest.Description;
Kedar Gupta7c4d1962015-08-03 10:46:04 -070024import org.hamcrest.Matchers;
Ray Milkey1f95bd32014-12-10 11:11:00 -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;
31import org.onlab.packet.IpAddress;
32import org.onlab.packet.MacAddress;
33import org.onlab.rest.BaseResource;
34import org.onosproject.codec.CodecService;
35import org.onosproject.codec.impl.CodecManager;
36import org.onosproject.net.DefaultHost;
37import org.onosproject.net.DeviceId;
38import org.onosproject.net.Host;
39import org.onosproject.net.HostId;
40import org.onosproject.net.HostLocation;
Kedar Gupta7c4d1962015-08-03 10:46:04 -070041import org.onosproject.net.host.HostProviderRegistry;
42import org.onosproject.net.host.HostProviderService;
Ray Milkey1f95bd32014-12-10 11:11:00 -080043import org.onosproject.net.host.HostService;
44import org.onosproject.net.provider.ProviderId;
45
Jian Li9d616492016-03-09 10:52:49 -080046import javax.ws.rs.NotFoundException;
47import javax.ws.rs.client.Entity;
48import javax.ws.rs.client.WebTarget;
Kedar Gupta7c4d1962015-08-03 10:46:04 -070049import javax.ws.rs.core.MediaType;
Jian Li9d616492016-03-09 10:52:49 -080050import javax.ws.rs.core.Response;
51import java.io.InputStream;
52import java.net.HttpURLConnection;
53import java.util.HashSet;
54import java.util.Set;
Kedar Gupta7c4d1962015-08-03 10:46:04 -070055
Jian Li9d616492016-03-09 10:52:49 -080056import static org.easymock.EasyMock.anyBoolean;
57import static org.easymock.EasyMock.anyObject;
58import static org.easymock.EasyMock.createMock;
59import static org.easymock.EasyMock.expect;
60import static org.easymock.EasyMock.expectLastCall;
61import static org.easymock.EasyMock.replay;
62import static org.easymock.EasyMock.verify;
Ray Milkey1f95bd32014-12-10 11:11:00 -080063import static org.hamcrest.Matchers.containsString;
64import static org.hamcrest.Matchers.hasSize;
65import static org.hamcrest.Matchers.is;
66import static org.hamcrest.Matchers.notNullValue;
67import static org.junit.Assert.assertThat;
Ray Milkey02f446b2014-12-11 20:19:43 -080068import static org.junit.Assert.fail;
Ray Milkey1f95bd32014-12-10 11:11:00 -080069import static org.onlab.packet.MacAddress.valueOf;
70import static org.onlab.packet.VlanId.vlanId;
71import static org.onosproject.net.PortNumber.portNumber;
72
73/**
74 * Simple example on how to write a JAX-RS unit test using Jersey test framework.
75 * A base class should/will be created to provide further assistance for testing.
76 */
Ray Milkey9c3d3362015-01-28 10:39:56 -080077public class HostResourceTest extends ResourceTest {
Ray Milkey1f95bd32014-12-10 11:11:00 -080078 final HostService mockHostService = createMock(HostService.class);
Kedar Gupta7c4d1962015-08-03 10:46:04 -070079 final HostProviderRegistry mockHostProviderRegistry = createMock(HostProviderRegistry.class);
80 final HostProviderService mockHostProviderService = createMock(HostProviderService.class);
Ray Milkey1f95bd32014-12-10 11:11:00 -080081 final HashSet<Host> hosts = new HashSet<>();
82
Ray Milkeyed0b1662015-02-05 09:34:29 -080083 /**
84 * Initializes test mocks and environment.
85 */
Ray Milkey1f95bd32014-12-10 11:11:00 -080086 @Before
Ray Milkeyed0b1662015-02-05 09:34:29 -080087 public void setUpTest() {
Ray Milkey1f95bd32014-12-10 11:11:00 -080088 expect(mockHostService.getHosts()).andReturn(hosts).anyTimes();
89
90 // Register the services needed for the test
91 final CodecManager codecService = new CodecManager();
92 codecService.activate();
93 ServiceDirectory testDirectory =
94 new TestServiceDirectory()
95 .add(HostService.class, mockHostService)
Kedar Gupta7c4d1962015-08-03 10:46:04 -070096 .add(CodecService.class, codecService)
97 .add(HostProviderRegistry.class, mockHostProviderRegistry);
Ray Milkey1f95bd32014-12-10 11:11:00 -080098 BaseResource.setServiceDirectory(testDirectory);
99 }
100
Ray Milkeyed0b1662015-02-05 09:34:29 -0800101 /**
102 * Verifies mocks.
103 */
Ray Milkey1f95bd32014-12-10 11:11:00 -0800104 @After
Ray Milkeyed0b1662015-02-05 09:34:29 -0800105 public void tearDownTest() {
Ray Milkey1f95bd32014-12-10 11:11:00 -0800106 verify(mockHostService);
107 }
108
109 /**
110 * Hamcrest matcher to check that a host representation in JSON matches
111 * the actual host.
112 */
113 public static class HostJsonMatcher extends TypeSafeMatcher<JsonObject> {
114 private final Host host;
115 private String reason = "";
116
117 public HostJsonMatcher(Host hostValue) {
118 host = hostValue;
119 }
120
121 @Override
122 public boolean matchesSafely(JsonObject jsonHost) {
123 // Check id
124 final String jsonId = jsonHost.get("id").asString();
125 if (!jsonId.equals(host.id().toString())) {
126 reason = "id " + host.id().toString();
127 return false;
128 }
129
130 // Check vlan id
131 final String jsonVlanId = jsonHost.get("vlan").asString();
132 if (!jsonVlanId.equals(host.vlan().toString())) {
133 reason = "vlan id " + host.vlan().toString();
134 return false;
135 }
136
137 // Check mac address
138 final String jsonMacAddress = jsonHost.get("mac").asString();
139 if (!jsonMacAddress.equals(host.mac().toString())) {
140 reason = "mac address " + host.mac().toString();
141 return false;
142 }
143
144 // Check location element id
145 final JsonObject jsonLocation = jsonHost.get("location").asObject();
146 final String jsonLocationElementId = jsonLocation.get("elementId").asString();
147 if (!jsonLocationElementId.equals(host.location().elementId().toString())) {
148 reason = "location element id " + host.location().elementId().toString();
149 return false;
150 }
151
152 // Check location port number
153 final String jsonLocationPortNumber = jsonLocation.get("port").asString();
154 if (!jsonLocationPortNumber.equals(host.location().port().toString())) {
155 reason = "location portNumber " + host.location().port().toString();
156 return false;
157 }
158
159 // Check Ip Addresses
160 final JsonArray jsonHostIps = jsonHost.get("ipAddresses").asArray();
161 final Set<IpAddress> expectedHostIps = host.ipAddresses();
162 if (jsonHostIps.size() != expectedHostIps.size()) {
163 reason = "IP address arrays differ in size";
164 return false;
165 }
166
167 return true;
168 }
169
170 @Override
171 public void describeTo(Description description) {
172 description.appendText(reason);
173 }
174 }
175
176 /**
177 * Factory to allocate a host array matcher.
178 *
179 * @param host host object we are looking for
180 * @return matcher
181 */
182 private static HostJsonMatcher matchesHost(Host host) {
183 return new HostJsonMatcher(host);
184 }
185
186 /**
187 * Hamcrest matcher to check that a host is represented properly in a JSON
188 * array of hosts.
189 */
190 public static class HostJsonArrayMatcher extends TypeSafeMatcher<JsonArray> {
191 private final Host host;
192 private String reason = "";
193
194 public HostJsonArrayMatcher(Host hostValue) {
195 host = hostValue;
196 }
197
198 @Override
199 public boolean matchesSafely(JsonArray json) {
200 boolean hostFound = false;
201 final int expectedAttributes = 5;
202 for (int jsonHostIndex = 0; jsonHostIndex < json.size();
203 jsonHostIndex++) {
204
205 final JsonObject jsonHost = json.get(jsonHostIndex).asObject();
206
207 if (jsonHost.names().size() != expectedAttributes) {
208 reason = "Found a host with the wrong number of attributes";
209 return false;
210 }
211
212 final String jsonHostId = jsonHost.get("id").asString();
213 if (jsonHostId.equals(host.id().toString())) {
214 hostFound = true;
215
216 // We found the correct host, check attribute values
217 assertThat(jsonHost, matchesHost(host));
218 }
219 }
220 if (!hostFound) {
221 reason = "Host with id " + host.id().toString() + " not found";
222 return false;
223 } else {
224 return true;
225 }
226 }
227
228 @Override
229 public void describeTo(Description description) {
230 description.appendText(reason);
231 }
232 }
233
234 /**
235 * Factory to allocate a host array matcher.
236 *
237 * @param host host object we are looking for
238 * @return matcher
239 */
240 private static HostJsonArrayMatcher hasHost(Host host) {
241 return new HostJsonArrayMatcher(host);
242 }
243
244 /**
245 * Tests the result of the rest api GET when there are no hosts.
246 */
247 @Test
248 public void testHostsEmptyArray() {
249 replay(mockHostService);
Jian Li9d616492016-03-09 10:52:49 -0800250 WebTarget wt = target();
251 String response = wt.path("hosts").request().get(String.class);
Ray Milkey1f95bd32014-12-10 11:11:00 -0800252 assertThat(response, is("{\"hosts\":[]}"));
253 }
254
255 /**
256 * Tests the result of the rest api GET when hosts are defined.
257 */
258 @Test
259 public void testHostsArray() {
260 replay(mockHostService);
261 final ProviderId pid = new ProviderId("of", "foo");
262 final MacAddress mac1 = MacAddress.valueOf("00:00:11:00:00:01");
263 final Set<IpAddress> ips1 = ImmutableSet.of(IpAddress.valueOf("1111:1111:1111:1::"));
264 final Host host1 =
265 new DefaultHost(pid, HostId.hostId(mac1), valueOf(1), vlanId((short) 1),
266 new HostLocation(DeviceId.deviceId("1"), portNumber(11), 1),
267 ips1);
268 final MacAddress mac2 = MacAddress.valueOf("00:00:11:00:00:02");
269 final Set<IpAddress> ips2 = ImmutableSet.of(
270 IpAddress.valueOf("2222:2222:2222:1::"),
271 IpAddress.valueOf("2222:2222:2222:2::"));
272 final Host host2 =
273 new DefaultHost(pid, HostId.hostId(mac2), valueOf(2), vlanId((short) 2),
274 new HostLocation(DeviceId.deviceId("2"), portNumber(22), 2),
275 ips2);
276 hosts.add(host1);
277 hosts.add(host2);
Jian Li9d616492016-03-09 10:52:49 -0800278 WebTarget wt = target();
279 String response = wt.path("hosts").request().get(String.class);
Ray Milkey1f95bd32014-12-10 11:11:00 -0800280 assertThat(response, containsString("{\"hosts\":["));
281
Jian Li80cfe452016-01-14 16:04:58 -0800282 final JsonObject result = Json.parse(response).asObject();
Ray Milkey1f95bd32014-12-10 11:11:00 -0800283 assertThat(result, notNullValue());
284
285 assertThat(result.names(), hasSize(1));
286 assertThat(result.names().get(0), is("hosts"));
287
288 final JsonArray hosts = result.get("hosts").asArray();
289 assertThat(hosts, notNullValue());
290
291 assertThat(hosts, hasHost(host1));
292 assertThat(hosts, hasHost(host2));
293 }
294
295 /**
296 * Tests fetch of one host by Id.
297 */
298 @Test
299 public void testSingleHostByIdFetch() {
300 final ProviderId pid = new ProviderId("of", "foo");
301 final MacAddress mac1 = MacAddress.valueOf("00:00:11:00:00:01");
302 final Set<IpAddress> ips1 = ImmutableSet.of(IpAddress.valueOf("1111:1111:1111:1::"));
303 final Host host1 =
304 new DefaultHost(pid, HostId.hostId(mac1), valueOf(1), vlanId((short) 1),
305 new HostLocation(DeviceId.deviceId("1"), portNumber(11), 1),
306 ips1);
307
308 hosts.add(host1);
309
310 expect(mockHostService.getHost(HostId.hostId("00:00:11:00:00:01/1")))
311 .andReturn(host1)
312 .anyTimes();
313 replay(mockHostService);
314
Jian Li9d616492016-03-09 10:52:49 -0800315 WebTarget wt = target();
316 String response = wt.path("hosts/00:00:11:00:00:01%2F1").request().get(String.class);
Jian Li80cfe452016-01-14 16:04:58 -0800317 final JsonObject result = Json.parse(response).asObject();
Ray Milkey1f95bd32014-12-10 11:11:00 -0800318 assertThat(result, matchesHost(host1));
319 }
320
321 /**
322 * Tests fetch of one host by mac and vlan.
323 */
324 @Test
325 public void testSingleHostByMacAndVlanFetch() {
326 final ProviderId pid = new ProviderId("of", "foo");
327 final MacAddress mac1 = MacAddress.valueOf("00:00:11:00:00:01");
328 final Set<IpAddress> ips1 = ImmutableSet.of(IpAddress.valueOf("1111:1111:1111:1::"));
329 final Host host1 =
330 new DefaultHost(pid, HostId.hostId(mac1), valueOf(1), vlanId((short) 1),
331 new HostLocation(DeviceId.deviceId("1"), portNumber(11), 1),
332 ips1);
333
334 hosts.add(host1);
335
336 expect(mockHostService.getHost(HostId.hostId("00:00:11:00:00:01/1")))
337 .andReturn(host1)
338 .anyTimes();
339 replay(mockHostService);
340
Jian Li9d616492016-03-09 10:52:49 -0800341 WebTarget wt = target();
342 String response = wt.path("hosts/00:00:11:00:00:01/1").request().get(String.class);
Jian Li80cfe452016-01-14 16:04:58 -0800343 final JsonObject result = Json.parse(response).asObject();
Ray Milkey1f95bd32014-12-10 11:11:00 -0800344 assertThat(result, matchesHost(host1));
345 }
346
Ray Milkey02f446b2014-12-11 20:19:43 -0800347 /**
348 * Tests that a fetch of a non-existent object throws an exception.
349 */
350 @Test
351 public void testBadGet() {
352
353 expect(mockHostService.getHost(HostId.hostId("00:00:11:00:00:01/1")))
354 .andReturn(null)
355 .anyTimes();
356 replay(mockHostService);
357
Jian Li9d616492016-03-09 10:52:49 -0800358 WebTarget wt = target();
Ray Milkey02f446b2014-12-11 20:19:43 -0800359 try {
Jian Li9d616492016-03-09 10:52:49 -0800360 wt.path("hosts/00:00:11:00:00:01/1").request().get(String.class);
Ray Milkey02f446b2014-12-11 20:19:43 -0800361 fail("Fetch of non-existent host did not throw an exception");
Jian Li9d616492016-03-09 10:52:49 -0800362 } catch (NotFoundException ex) {
Ray Milkey02f446b2014-12-11 20:19:43 -0800363 assertThat(ex.getMessage(),
Jian Li9d616492016-03-09 10:52:49 -0800364 containsString("HTTP 404 Not Found"));
Ray Milkey02f446b2014-12-11 20:19:43 -0800365 }
366 }
367
Kedar Gupta7c4d1962015-08-03 10:46:04 -0700368 /**
369 * Tests post of a single host via JSON stream.
370 */
371 @Test
372 public void testPost() {
Ray Milkeydc083442016-02-22 11:27:57 -0800373 mockHostProviderService.hostDetected(anyObject(), anyObject(), anyBoolean());
Kedar Gupta7c4d1962015-08-03 10:46:04 -0700374 expectLastCall();
375 replay(mockHostProviderService);
376
377 expect(mockHostProviderRegistry.register(anyObject())).andReturn(mockHostProviderService);
378 mockHostProviderRegistry.unregister(anyObject());
379 expectLastCall();
380 replay(mockHostProviderRegistry);
381
382 replay(mockHostService);
383
Phaneendra Manda2be2f882015-11-11 15:23:40 +0530384 InputStream jsonStream = HostResourceTest.class
Kedar Gupta7c4d1962015-08-03 10:46:04 -0700385 .getResourceAsStream("post-host.json");
Jian Li9d616492016-03-09 10:52:49 -0800386 WebTarget wt = target();
Kedar Gupta7c4d1962015-08-03 10:46:04 -0700387
Jian Li9d616492016-03-09 10:52:49 -0800388 Response response = wt.path("hosts")
389 .request(MediaType.APPLICATION_JSON_TYPE)
390 .post(Entity.json(jsonStream));
Kedar Gupta7c4d1962015-08-03 10:46:04 -0700391 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
392 String location = response.getLocation().getPath();
393 assertThat(location, Matchers.startsWith("/hosts/11:22:33:44:55:66/-1"));
394 }
Ray Milkey1f95bd32014-12-10 11:11:00 -0800395}
396