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