blob: 76d9a8de89f3edb7b1205833c689122c92e044a8 [file] [log] [blame]
Jian Lif96d41f2016-05-03 09:49:12 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Jian Lif96d41f2016-05-03 09:49:12 -07003 *
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.resources;
17
18import com.eclipsesource.json.Json;
19import com.eclipsesource.json.JsonArray;
20import com.eclipsesource.json.JsonObject;
21import com.google.common.collect.ImmutableList;
22import com.google.common.collect.ImmutableSet;
23import org.apache.commons.lang3.StringUtils;
24import org.hamcrest.Description;
Jian Li0409b702016-05-03 18:21:37 -070025import org.hamcrest.Matchers;
Jian Lif96d41f2016-05-03 09:49:12 -070026import org.hamcrest.TypeSafeMatcher;
27import org.junit.Before;
28import org.junit.Test;
29import org.onlab.osgi.ServiceDirectory;
30import org.onlab.osgi.TestServiceDirectory;
Jian Lif96d41f2016-05-03 09:49:12 -070031import org.onosproject.cluster.NodeId;
32import org.onosproject.cluster.RoleInfo;
33import org.onosproject.codec.CodecService;
34import org.onosproject.codec.impl.CodecManager;
35import org.onosproject.mastership.MastershipAdminService;
36import org.onosproject.mastership.MastershipService;
Kavitha Alagesan60093392016-10-26 17:04:26 +053037import org.onosproject.net.DefaultDevice;
38import org.onosproject.net.Device;
Jian Lif96d41f2016-05-03 09:49:12 -070039import org.onosproject.net.DeviceId;
40import org.onosproject.net.MastershipRole;
Kavitha Alagesan60093392016-10-26 17:04:26 +053041import org.onosproject.net.device.DeviceService;
Jian Lif96d41f2016-05-03 09:49:12 -070042
Jian Li0409b702016-05-03 18:21:37 -070043import javax.ws.rs.client.Entity;
Jian Lif96d41f2016-05-03 09:49:12 -070044import javax.ws.rs.client.WebTarget;
45import javax.ws.rs.core.Response;
Jian Li0409b702016-05-03 18:21:37 -070046import java.io.InputStream;
Jian Lif96d41f2016-05-03 09:49:12 -070047import java.net.HttpURLConnection;
48import java.util.List;
49import java.util.Set;
50
51import static org.easymock.EasyMock.anyObject;
52import static org.easymock.EasyMock.createMock;
53import static org.easymock.EasyMock.expect;
54import static org.easymock.EasyMock.expectLastCall;
55import static org.easymock.EasyMock.replay;
56import static org.hamcrest.Matchers.hasSize;
57import static org.hamcrest.Matchers.is;
58import static org.hamcrest.Matchers.notNullValue;
59import static org.junit.Assert.assertEquals;
60import static org.junit.Assert.assertThat;
61import static org.onosproject.net.MastershipRole.MASTER;
62
63/**
64 * Unit tests for Mastership REST APIs.
65 */
66public final class MastershipResourceTest extends ResourceTest {
67
68 private final MastershipService mockService = createMock(MastershipService.class);
Kavitha Alagesan60093392016-10-26 17:04:26 +053069 private final DeviceService mockDeviceService = createMock(DeviceService.class);
Jian Lif96d41f2016-05-03 09:49:12 -070070 private final MastershipAdminService mockAdminService =
71 createMock(MastershipAdminService.class);
72
73 private final DeviceId deviceId1 = DeviceId.deviceId("dev:1");
74 private final DeviceId deviceId2 = DeviceId.deviceId("dev:2");
75 private final DeviceId deviceId3 = DeviceId.deviceId("dev:3");
76
Kavitha Alagesan60093392016-10-26 17:04:26 +053077 final Device device1 = new DefaultDevice(null, deviceId1, Device.Type.OTHER,
78 "", "", "", "", null);
Jian Lif96d41f2016-05-03 09:49:12 -070079 private final NodeId nodeId1 = NodeId.nodeId("node:1");
80 private final NodeId nodeId2 = NodeId.nodeId("node:2");
81 private final NodeId nodeId3 = NodeId.nodeId("node:3");
82 private final MastershipRole role1 = MASTER;
83
84 /**
85 * Creates a mock role info which is comprised of one master and three backups.
86 *
87 * @return a mock role info instance
88 */
89 private RoleInfo createMockRoleInfo() {
90 NodeId master = NodeId.nodeId("master");
91 List<NodeId> backups = ImmutableList.of(nodeId1, nodeId2, nodeId3);
92
93 return new RoleInfo(master, backups);
94 }
95
96 private static final class RoleInfoJsonMatcher extends TypeSafeMatcher<JsonObject> {
97 private final RoleInfo roleInfo;
98 private String reason = "";
99
100 private RoleInfoJsonMatcher(RoleInfo roleInfo) {
101 this.roleInfo = roleInfo;
102 }
103
104 @Override
105 protected boolean matchesSafely(JsonObject jsonNode) {
106
107 // check master node identifier
108 String jsonNodeId = jsonNode.get("master") != null ?
109 jsonNode.get("master").asString() : null;
110 String nodeId = roleInfo.master().id();
111 if (!StringUtils.equals(jsonNodeId, nodeId)) {
112 reason = "master's node id was " + jsonNodeId;
113 return false;
114 }
115
116 // check backup nodes size
117 final JsonArray jsonBackupNodeIds = jsonNode.get("backups").asArray();
118 if (jsonBackupNodeIds.size() != roleInfo.backups().size()) {
119 reason = "backup nodes size was " + jsonBackupNodeIds.size();
120 return false;
121 }
122
123 // check backup nodes' identifier
124 for (NodeId backupNodeId : roleInfo.backups()) {
125 boolean backupFound = false;
126 for (int idx = 0; idx < jsonBackupNodeIds.size(); idx++) {
127 if (backupNodeId.id().equals(jsonBackupNodeIds.get(idx).asString())) {
128 backupFound = true;
129 break;
130 }
131 }
132 if (!backupFound) {
133 reason = "backup not found " + backupNodeId.id();
134 return false;
135 }
136 }
137
138 return true;
139 }
140
141 @Override
142 public void describeTo(Description description) {
143 description.appendText(reason);
144 }
145 }
146
147 /**
148 * Factory to allocate a role info json matcher.
149 *
150 * @param roleInfo role info object we are looking for
151 * @return matcher
152 */
153 private static RoleInfoJsonMatcher matchesRoleInfo(RoleInfo roleInfo) {
154 return new RoleInfoJsonMatcher(roleInfo);
155 }
156
157 /**
158 * Sets up the global values for all the tests.
159 */
160 @Before
161 public void setUpTest() {
162
163 final CodecManager codecService = new CodecManager();
164 codecService.activate();
165 ServiceDirectory testDirectory =
166 new TestServiceDirectory()
167 .add(MastershipService.class, mockService)
168 .add(MastershipAdminService.class, mockAdminService)
Kavitha Alagesan60093392016-10-26 17:04:26 +0530169 .add(DeviceService.class, mockDeviceService)
Jian Lif96d41f2016-05-03 09:49:12 -0700170 .add(CodecService.class, codecService);
171
Ray Milkey094a1352018-01-22 14:03:54 -0800172 setServiceDirectory(testDirectory);
Jian Lif96d41f2016-05-03 09:49:12 -0700173 }
174
175 /**
176 * Tests the result of the REST API GET when there are active master roles.
177 */
178 @Test
179 public void testGetLocalRole() {
180 expect(mockService.getLocalRole(anyObject())).andReturn(role1).anyTimes();
181 replay(mockService);
182
183 final WebTarget wt = target();
184 final String response = wt.path("mastership/" + deviceId1.toString() +
185 "/local").request().get(String.class);
186 final JsonObject result = Json.parse(response).asObject();
187 assertThat(result, notNullValue());
188
189 assertThat(result.names(), hasSize(1));
190 assertThat(result.names().get(0), is("role"));
191
192 final String role = result.get("role").asString();
193 assertThat(role, notNullValue());
194 assertThat(role, is("MASTER"));
195 }
196
197 /**
198 * Tests the result of the REST API GET when there is no active master.
199 */
200 @Test
201 public void testGetMasterForNull() {
202 expect(mockService.getMasterFor(anyObject())).andReturn(null).anyTimes();
203 replay(mockService);
204
205 final WebTarget wt = target();
206 final Response response = wt.path("mastership/" + deviceId1.toString() +
207 "/master").request().get();
208 assertEquals(404, response.getStatus());
209 }
210
211 /**
212 * Tests the result of the REST API GET when there is active master.
213 */
214 @Test
215 public void testGetMasterFor() {
216 expect(mockService.getMasterFor(anyObject())).andReturn(nodeId1).anyTimes();
217 replay(mockService);
218
219 final WebTarget wt = target();
220 final String response = wt.path("mastership/" + deviceId1.toString() +
221 "/master").request().get(String.class);
222 final JsonObject result = Json.parse(response).asObject();
223 assertThat(result, notNullValue());
224
225 assertThat(result.names(), hasSize(1));
Jian Li0409b702016-05-03 18:21:37 -0700226 assertThat(result.names().get(0), is("nodeId"));
Jian Lif96d41f2016-05-03 09:49:12 -0700227
Jian Li0409b702016-05-03 18:21:37 -0700228 final String node = result.get("nodeId").asString();
Jian Lif96d41f2016-05-03 09:49:12 -0700229 assertThat(node, notNullValue());
230 assertThat(node, is("node:1"));
231 }
232
233 /**
234 * Tests the result of the REST API GET when there are no active nodes.
235 */
236 @Test
237 public void testGetNodesForNull() {
238 expect(mockService.getNodesFor(anyObject())).andReturn(null).anyTimes();
239 replay(mockService);
240
241 final WebTarget wt = target();
242 final Response response = wt.path("mastership/" + deviceId1.toString() +
243 "/role").request().get();
244 assertEquals(404, response.getStatus());
245 }
246
247 /**
248 * Tests the result of the REST API GET when there are active nodes.
249 */
250 @Test
251 public void testGetNodesFor() {
252 RoleInfo mockRoleInfo = createMockRoleInfo();
253 expect(mockService.getNodesFor(anyObject())).andReturn(mockRoleInfo).anyTimes();
254 replay(mockService);
255
256 final WebTarget wt = target();
257 final String response = wt.path("mastership/" + deviceId1.toString() +
258 "/role").request().get(String.class);
259 final JsonObject result = Json.parse(response).asObject();
260 assertThat(result, notNullValue());
261
262 assertThat(result, matchesRoleInfo(mockRoleInfo));
263 }
264
265 /**
266 * Tests the result of the REST API GET when there are active devices.
267 */
268 @Test
269 public void testGetDevicesOf() {
270 Set<DeviceId> deviceIds = ImmutableSet.of(deviceId1, deviceId2, deviceId3);
271 expect(mockService.getDevicesOf(anyObject())).andReturn(deviceIds).anyTimes();
272 replay(mockService);
273
274 final WebTarget wt = target();
275 final String response = wt.path("mastership/" + deviceId1.toString() +
276 "/device").request().get(String.class);
277 final JsonObject result = Json.parse(response).asObject();
278 assertThat(result, notNullValue());
279
280 assertThat(result.names(), hasSize(1));
Jian Li0409b702016-05-03 18:21:37 -0700281 assertThat(result.names().get(0), is("deviceIds"));
Jian Lif96d41f2016-05-03 09:49:12 -0700282
Jian Li0409b702016-05-03 18:21:37 -0700283 final JsonArray jsonDevices = result.get("deviceIds").asArray();
Jian Lif96d41f2016-05-03 09:49:12 -0700284 assertThat(jsonDevices, notNullValue());
285 assertThat(jsonDevices.size(), is(3));
286 }
287
288 /**
289 * Tests the result of the REST API GET for requesting mastership role.
290 */
291 @Test
292 public void testRequestRoleFor() {
Jian Li0409b702016-05-03 18:21:37 -0700293 expect(mockService.requestRoleForSync(anyObject())).andReturn(role1).anyTimes();
294 replay(mockService);
295
Kavitha Alagesan60093392016-10-26 17:04:26 +0530296 expect(mockDeviceService.getDevice(deviceId1)).andReturn(device1);
297 replay(mockDeviceService);
298
Jian Li0409b702016-05-03 18:21:37 -0700299 final WebTarget wt = target();
300 final String response = wt.path("mastership/" + deviceId1.toString() +
301 "/request").request().get(String.class);
302 final JsonObject result = Json.parse(response).asObject();
303 assertThat(result, notNullValue());
304
305 assertThat(result.names(), hasSize(1));
306 assertThat(result.names().get(0), is("role"));
307
308 final String role = result.get("role").asString();
309 assertThat(role, notNullValue());
310 assertThat(role, is("MASTER"));
Jian Lif96d41f2016-05-03 09:49:12 -0700311 }
312
313 /**
314 * Tests the result of the REST API GET for relinquishing mastership role.
315 */
316 @Test
317 public void testRelinquishMastership() {
Jian Li0409b702016-05-03 18:21:37 -0700318 mockService.relinquishMastershipSync(anyObject());
319 expectLastCall();
320 replay(mockService);
321
322 final WebTarget wt = target();
323 final Response response = wt.path("mastership/" + deviceId1.toString() +
324 "/relinquish").request().get();
325 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
326 String location = response.getLocation().toString();
327 assertThat(location, Matchers.startsWith(deviceId1.toString()));
Jian Lif96d41f2016-05-03 09:49:12 -0700328 }
329
330 /**
331 * Tests the result of the REST API PUT for setting role.
332 */
333 @Test
334 public void testSetRole() {
Jian Li0409b702016-05-03 18:21:37 -0700335 mockAdminService.setRoleSync(anyObject(), anyObject(), anyObject());
336 expectLastCall();
337 replay(mockAdminService);
338
339 final WebTarget wt = target();
340 final InputStream jsonStream = MetersResourceTest.class
341 .getResourceAsStream("put-set-roles.json");
342 final Response response = wt.path("mastership")
343 .request().put(Entity.json(jsonStream));
344 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
Jian Lif96d41f2016-05-03 09:49:12 -0700345 }
346
347 /**
348 * Tests the result of the REST API GET for balancing roles.
349 */
350 @Test
351 public void testBalanceRoles() {
352 mockAdminService.balanceRoles();
353 expectLastCall();
354 replay(mockAdminService);
355
356 final WebTarget wt = target();
357 final Response response = wt.path("mastership").request().get();
358 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
359 }
360}