blob: 4221846ac3018097948fca809e8eddf49189b851 [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
Kedar Gupta7c4d1962015-08-03 10:46:04 -070019import java.io.InputStream;
20import java.net.HttpURLConnection;
Ray Milkey1f95bd32014-12-10 11:11:00 -080021import java.util.HashSet;
22import java.util.Set;
23
Jian Li80cfe452016-01-14 16:04:58 -080024import com.eclipsesource.json.Json;
Kedar Gupta7c4d1962015-08-03 10:46:04 -070025import com.sun.jersey.api.client.ClientResponse;
Ray Milkey1f95bd32014-12-10 11:11:00 -080026import org.hamcrest.Description;
Kedar Gupta7c4d1962015-08-03 10:46:04 -070027import org.hamcrest.Matchers;
Ray Milkey1f95bd32014-12-10 11:11:00 -080028import org.hamcrest.TypeSafeMatcher;
29import org.junit.After;
30import org.junit.Before;
31import org.junit.Test;
32import org.onlab.osgi.ServiceDirectory;
33import org.onlab.osgi.TestServiceDirectory;
34import org.onlab.packet.IpAddress;
35import org.onlab.packet.MacAddress;
36import org.onlab.rest.BaseResource;
37import org.onosproject.codec.CodecService;
38import org.onosproject.codec.impl.CodecManager;
39import org.onosproject.net.DefaultHost;
40import org.onosproject.net.DeviceId;
41import org.onosproject.net.Host;
42import org.onosproject.net.HostId;
43import org.onosproject.net.HostLocation;
Kedar Gupta7c4d1962015-08-03 10:46:04 -070044import org.onosproject.net.host.HostProviderRegistry;
45import org.onosproject.net.host.HostProviderService;
Ray Milkey1f95bd32014-12-10 11:11:00 -080046import org.onosproject.net.host.HostService;
47import org.onosproject.net.provider.ProviderId;
48
49import com.eclipsesource.json.JsonArray;
50import com.eclipsesource.json.JsonObject;
51import com.google.common.collect.ImmutableSet;
Ray Milkey02f446b2014-12-11 20:19:43 -080052import com.sun.jersey.api.client.UniformInterfaceException;
Ray Milkey1f95bd32014-12-10 11:11:00 -080053import com.sun.jersey.api.client.WebResource;
Ray Milkey1f95bd32014-12-10 11:11:00 -080054
Kedar Gupta7c4d1962015-08-03 10:46:04 -070055import javax.ws.rs.core.MediaType;
56
57import static org.easymock.EasyMock.*;
Ray Milkey1f95bd32014-12-10 11:11:00 -080058import static org.hamcrest.Matchers.containsString;
59import static org.hamcrest.Matchers.hasSize;
60import static org.hamcrest.Matchers.is;
61import static org.hamcrest.Matchers.notNullValue;
62import static org.junit.Assert.assertThat;
Ray Milkey02f446b2014-12-11 20:19:43 -080063import static org.junit.Assert.fail;
Ray Milkey1f95bd32014-12-10 11:11:00 -080064import static org.onlab.packet.MacAddress.valueOf;
65import static org.onlab.packet.VlanId.vlanId;
66import static org.onosproject.net.PortNumber.portNumber;
67
68/**
69 * Simple example on how to write a JAX-RS unit test using Jersey test framework.
70 * A base class should/will be created to provide further assistance for testing.
71 */
Ray Milkey9c3d3362015-01-28 10:39:56 -080072public class HostResourceTest extends ResourceTest {
Ray Milkey1f95bd32014-12-10 11:11:00 -080073 final HostService mockHostService = createMock(HostService.class);
Kedar Gupta7c4d1962015-08-03 10:46:04 -070074 final HostProviderRegistry mockHostProviderRegistry = createMock(HostProviderRegistry.class);
75 final HostProviderService mockHostProviderService = createMock(HostProviderService.class);
Ray Milkey1f95bd32014-12-10 11:11:00 -080076 final HashSet<Host> hosts = new HashSet<>();
77
Ray Milkeyed0b1662015-02-05 09:34:29 -080078 /**
79 * Initializes test mocks and environment.
80 */
Ray Milkey1f95bd32014-12-10 11:11:00 -080081 @Before
Ray Milkeyed0b1662015-02-05 09:34:29 -080082 public void setUpTest() {
Ray Milkey1f95bd32014-12-10 11:11:00 -080083 expect(mockHostService.getHosts()).andReturn(hosts).anyTimes();
84
85 // Register the services needed for the test
86 final CodecManager codecService = new CodecManager();
87 codecService.activate();
88 ServiceDirectory testDirectory =
89 new TestServiceDirectory()
90 .add(HostService.class, mockHostService)
Kedar Gupta7c4d1962015-08-03 10:46:04 -070091 .add(CodecService.class, codecService)
92 .add(HostProviderRegistry.class, mockHostProviderRegistry);
Ray Milkey1f95bd32014-12-10 11:11:00 -080093 BaseResource.setServiceDirectory(testDirectory);
94 }
95
Ray Milkeyed0b1662015-02-05 09:34:29 -080096 /**
97 * Verifies mocks.
98 */
Ray Milkey1f95bd32014-12-10 11:11:00 -080099 @After
Ray Milkeyed0b1662015-02-05 09:34:29 -0800100 public void tearDownTest() {
Ray Milkey1f95bd32014-12-10 11:11:00 -0800101 verify(mockHostService);
102 }
103
104 /**
105 * Hamcrest matcher to check that a host representation in JSON matches
106 * the actual host.
107 */
108 public static class HostJsonMatcher extends TypeSafeMatcher<JsonObject> {
109 private final Host host;
110 private String reason = "";
111
112 public HostJsonMatcher(Host hostValue) {
113 host = hostValue;
114 }
115
116 @Override
117 public boolean matchesSafely(JsonObject jsonHost) {
118 // Check id
119 final String jsonId = jsonHost.get("id").asString();
120 if (!jsonId.equals(host.id().toString())) {
121 reason = "id " + host.id().toString();
122 return false;
123 }
124
125 // Check vlan id
126 final String jsonVlanId = jsonHost.get("vlan").asString();
127 if (!jsonVlanId.equals(host.vlan().toString())) {
128 reason = "vlan id " + host.vlan().toString();
129 return false;
130 }
131
132 // Check mac address
133 final String jsonMacAddress = jsonHost.get("mac").asString();
134 if (!jsonMacAddress.equals(host.mac().toString())) {
135 reason = "mac address " + host.mac().toString();
136 return false;
137 }
138
139 // Check location element id
140 final JsonObject jsonLocation = jsonHost.get("location").asObject();
141 final String jsonLocationElementId = jsonLocation.get("elementId").asString();
142 if (!jsonLocationElementId.equals(host.location().elementId().toString())) {
143 reason = "location element id " + host.location().elementId().toString();
144 return false;
145 }
146
147 // Check location port number
148 final String jsonLocationPortNumber = jsonLocation.get("port").asString();
149 if (!jsonLocationPortNumber.equals(host.location().port().toString())) {
150 reason = "location portNumber " + host.location().port().toString();
151 return false;
152 }
153
154 // Check Ip Addresses
155 final JsonArray jsonHostIps = jsonHost.get("ipAddresses").asArray();
156 final Set<IpAddress> expectedHostIps = host.ipAddresses();
157 if (jsonHostIps.size() != expectedHostIps.size()) {
158 reason = "IP address arrays differ in size";
159 return false;
160 }
161
162 return true;
163 }
164
165 @Override
166 public void describeTo(Description description) {
167 description.appendText(reason);
168 }
169 }
170
171 /**
172 * Factory to allocate a host array matcher.
173 *
174 * @param host host object we are looking for
175 * @return matcher
176 */
177 private static HostJsonMatcher matchesHost(Host host) {
178 return new HostJsonMatcher(host);
179 }
180
181 /**
182 * Hamcrest matcher to check that a host is represented properly in a JSON
183 * array of hosts.
184 */
185 public static class HostJsonArrayMatcher extends TypeSafeMatcher<JsonArray> {
186 private final Host host;
187 private String reason = "";
188
189 public HostJsonArrayMatcher(Host hostValue) {
190 host = hostValue;
191 }
192
193 @Override
194 public boolean matchesSafely(JsonArray json) {
195 boolean hostFound = false;
196 final int expectedAttributes = 5;
197 for (int jsonHostIndex = 0; jsonHostIndex < json.size();
198 jsonHostIndex++) {
199
200 final JsonObject jsonHost = json.get(jsonHostIndex).asObject();
201
202 if (jsonHost.names().size() != expectedAttributes) {
203 reason = "Found a host with the wrong number of attributes";
204 return false;
205 }
206
207 final String jsonHostId = jsonHost.get("id").asString();
208 if (jsonHostId.equals(host.id().toString())) {
209 hostFound = true;
210
211 // We found the correct host, check attribute values
212 assertThat(jsonHost, matchesHost(host));
213 }
214 }
215 if (!hostFound) {
216 reason = "Host with id " + host.id().toString() + " not found";
217 return false;
218 } else {
219 return true;
220 }
221 }
222
223 @Override
224 public void describeTo(Description description) {
225 description.appendText(reason);
226 }
227 }
228
229 /**
230 * Factory to allocate a host array matcher.
231 *
232 * @param host host object we are looking for
233 * @return matcher
234 */
235 private static HostJsonArrayMatcher hasHost(Host host) {
236 return new HostJsonArrayMatcher(host);
237 }
238
239 /**
240 * Tests the result of the rest api GET when there are no hosts.
241 */
242 @Test
243 public void testHostsEmptyArray() {
244 replay(mockHostService);
245 WebResource rs = resource();
246 String response = rs.path("hosts").get(String.class);
247 assertThat(response, is("{\"hosts\":[]}"));
248 }
249
250 /**
251 * Tests the result of the rest api GET when hosts are defined.
252 */
253 @Test
254 public void testHostsArray() {
255 replay(mockHostService);
256 final ProviderId pid = new ProviderId("of", "foo");
257 final MacAddress mac1 = MacAddress.valueOf("00:00:11:00:00:01");
258 final Set<IpAddress> ips1 = ImmutableSet.of(IpAddress.valueOf("1111:1111:1111:1::"));
259 final Host host1 =
260 new DefaultHost(pid, HostId.hostId(mac1), valueOf(1), vlanId((short) 1),
261 new HostLocation(DeviceId.deviceId("1"), portNumber(11), 1),
262 ips1);
263 final MacAddress mac2 = MacAddress.valueOf("00:00:11:00:00:02");
264 final Set<IpAddress> ips2 = ImmutableSet.of(
265 IpAddress.valueOf("2222:2222:2222:1::"),
266 IpAddress.valueOf("2222:2222:2222:2::"));
267 final Host host2 =
268 new DefaultHost(pid, HostId.hostId(mac2), valueOf(2), vlanId((short) 2),
269 new HostLocation(DeviceId.deviceId("2"), portNumber(22), 2),
270 ips2);
271 hosts.add(host1);
272 hosts.add(host2);
273 WebResource rs = resource();
274 String response = rs.path("hosts").get(String.class);
275 assertThat(response, containsString("{\"hosts\":["));
276
Jian Li80cfe452016-01-14 16:04:58 -0800277 final JsonObject result = Json.parse(response).asObject();
Ray Milkey1f95bd32014-12-10 11:11:00 -0800278 assertThat(result, notNullValue());
279
280 assertThat(result.names(), hasSize(1));
281 assertThat(result.names().get(0), is("hosts"));
282
283 final JsonArray hosts = result.get("hosts").asArray();
284 assertThat(hosts, notNullValue());
285
286 assertThat(hosts, hasHost(host1));
287 assertThat(hosts, hasHost(host2));
288 }
289
290 /**
291 * Tests fetch of one host by Id.
292 */
293 @Test
294 public void testSingleHostByIdFetch() {
295 final ProviderId pid = new ProviderId("of", "foo");
296 final MacAddress mac1 = MacAddress.valueOf("00:00:11:00:00:01");
297 final Set<IpAddress> ips1 = ImmutableSet.of(IpAddress.valueOf("1111:1111:1111:1::"));
298 final Host host1 =
299 new DefaultHost(pid, HostId.hostId(mac1), valueOf(1), vlanId((short) 1),
300 new HostLocation(DeviceId.deviceId("1"), portNumber(11), 1),
301 ips1);
302
303 hosts.add(host1);
304
305 expect(mockHostService.getHost(HostId.hostId("00:00:11:00:00:01/1")))
306 .andReturn(host1)
307 .anyTimes();
308 replay(mockHostService);
309
310 WebResource rs = resource();
311 String response = rs.path("hosts/00:00:11:00:00:01%2F1").get(String.class);
Jian Li80cfe452016-01-14 16:04:58 -0800312 final JsonObject result = Json.parse(response).asObject();
Ray Milkey1f95bd32014-12-10 11:11:00 -0800313 assertThat(result, matchesHost(host1));
314 }
315
316 /**
317 * Tests fetch of one host by mac and vlan.
318 */
319 @Test
320 public void testSingleHostByMacAndVlanFetch() {
321 final ProviderId pid = new ProviderId("of", "foo");
322 final MacAddress mac1 = MacAddress.valueOf("00:00:11:00:00:01");
323 final Set<IpAddress> ips1 = ImmutableSet.of(IpAddress.valueOf("1111:1111:1111:1::"));
324 final Host host1 =
325 new DefaultHost(pid, HostId.hostId(mac1), valueOf(1), vlanId((short) 1),
326 new HostLocation(DeviceId.deviceId("1"), portNumber(11), 1),
327 ips1);
328
329 hosts.add(host1);
330
331 expect(mockHostService.getHost(HostId.hostId("00:00:11:00:00:01/1")))
332 .andReturn(host1)
333 .anyTimes();
334 replay(mockHostService);
335
336 WebResource rs = resource();
337 String response = rs.path("hosts/00:00:11:00:00:01/1").get(String.class);
Jian Li80cfe452016-01-14 16:04:58 -0800338 final JsonObject result = Json.parse(response).asObject();
Ray Milkey1f95bd32014-12-10 11:11:00 -0800339 assertThat(result, matchesHost(host1));
340 }
341
Ray Milkey02f446b2014-12-11 20:19:43 -0800342 /**
343 * Tests that a fetch of a non-existent object throws an exception.
344 */
345 @Test
346 public void testBadGet() {
347
348 expect(mockHostService.getHost(HostId.hostId("00:00:11:00:00:01/1")))
349 .andReturn(null)
350 .anyTimes();
351 replay(mockHostService);
352
353 WebResource rs = resource();
354 try {
355 rs.path("hosts/00:00:11:00:00:01/1").get(String.class);
356 fail("Fetch of non-existent host did not throw an exception");
357 } catch (UniformInterfaceException ex) {
358 assertThat(ex.getMessage(),
359 containsString("returned a response status of"));
360 }
361 }
362
Kedar Gupta7c4d1962015-08-03 10:46:04 -0700363 /**
364 * Tests post of a single host via JSON stream.
365 */
366 @Test
367 public void testPost() {
Ray Milkeydc083442016-02-22 11:27:57 -0800368 mockHostProviderService.hostDetected(anyObject(), anyObject(), anyBoolean());
Kedar Gupta7c4d1962015-08-03 10:46:04 -0700369 expectLastCall();
370 replay(mockHostProviderService);
371
372 expect(mockHostProviderRegistry.register(anyObject())).andReturn(mockHostProviderService);
373 mockHostProviderRegistry.unregister(anyObject());
374 expectLastCall();
375 replay(mockHostProviderRegistry);
376
377 replay(mockHostService);
378
Phaneendra Manda2be2f882015-11-11 15:23:40 +0530379 InputStream jsonStream = HostResourceTest.class
Kedar Gupta7c4d1962015-08-03 10:46:04 -0700380 .getResourceAsStream("post-host.json");
381 WebResource rs = resource();
382
383 ClientResponse response = rs.path("hosts")
384 .type(MediaType.APPLICATION_JSON_TYPE)
385 .post(ClientResponse.class, jsonStream);
386 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
387 String location = response.getLocation().getPath();
388 assertThat(location, Matchers.startsWith("/hosts/11:22:33:44:55:66/-1"));
389 }
Ray Milkey1f95bd32014-12-10 11:11:00 -0800390}
391