blob: 994e1381be0790bf8165316dbae143c5feff875f [file] [log] [blame]
Jian Lif96d41f2016-05-03 09:49:12 -07001/*
2 * Copyright 2016-present 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.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;
31import org.onlab.rest.BaseResource;
32import org.onosproject.cluster.NodeId;
33import org.onosproject.cluster.RoleInfo;
34import org.onosproject.codec.CodecService;
35import org.onosproject.codec.impl.CodecManager;
36import org.onosproject.mastership.MastershipAdminService;
37import org.onosproject.mastership.MastershipService;
38import org.onosproject.net.DeviceId;
39import org.onosproject.net.MastershipRole;
40
Jian Li0409b702016-05-03 18:21:37 -070041import javax.ws.rs.client.Entity;
Jian Lif96d41f2016-05-03 09:49:12 -070042import javax.ws.rs.client.WebTarget;
43import javax.ws.rs.core.Response;
Jian Li0409b702016-05-03 18:21:37 -070044import java.io.InputStream;
Jian Lif96d41f2016-05-03 09:49:12 -070045import java.net.HttpURLConnection;
46import java.util.List;
47import java.util.Set;
48
49import static org.easymock.EasyMock.anyObject;
50import static org.easymock.EasyMock.createMock;
51import static org.easymock.EasyMock.expect;
52import static org.easymock.EasyMock.expectLastCall;
53import static org.easymock.EasyMock.replay;
54import static org.hamcrest.Matchers.hasSize;
55import static org.hamcrest.Matchers.is;
56import static org.hamcrest.Matchers.notNullValue;
57import static org.junit.Assert.assertEquals;
58import static org.junit.Assert.assertThat;
59import static org.onosproject.net.MastershipRole.MASTER;
60
61/**
62 * Unit tests for Mastership REST APIs.
63 */
64public final class MastershipResourceTest extends ResourceTest {
65
66 private final MastershipService mockService = createMock(MastershipService.class);
67 private final MastershipAdminService mockAdminService =
68 createMock(MastershipAdminService.class);
69
70 private final DeviceId deviceId1 = DeviceId.deviceId("dev:1");
71 private final DeviceId deviceId2 = DeviceId.deviceId("dev:2");
72 private final DeviceId deviceId3 = DeviceId.deviceId("dev:3");
73
74 private final NodeId nodeId1 = NodeId.nodeId("node:1");
75 private final NodeId nodeId2 = NodeId.nodeId("node:2");
76 private final NodeId nodeId3 = NodeId.nodeId("node:3");
77 private final MastershipRole role1 = MASTER;
78
79 /**
80 * Creates a mock role info which is comprised of one master and three backups.
81 *
82 * @return a mock role info instance
83 */
84 private RoleInfo createMockRoleInfo() {
85 NodeId master = NodeId.nodeId("master");
86 List<NodeId> backups = ImmutableList.of(nodeId1, nodeId2, nodeId3);
87
88 return new RoleInfo(master, backups);
89 }
90
91 private static final class RoleInfoJsonMatcher extends TypeSafeMatcher<JsonObject> {
92 private final RoleInfo roleInfo;
93 private String reason = "";
94
95 private RoleInfoJsonMatcher(RoleInfo roleInfo) {
96 this.roleInfo = roleInfo;
97 }
98
99 @Override
100 protected boolean matchesSafely(JsonObject jsonNode) {
101
102 // check master node identifier
103 String jsonNodeId = jsonNode.get("master") != null ?
104 jsonNode.get("master").asString() : null;
105 String nodeId = roleInfo.master().id();
106 if (!StringUtils.equals(jsonNodeId, nodeId)) {
107 reason = "master's node id was " + jsonNodeId;
108 return false;
109 }
110
111 // check backup nodes size
112 final JsonArray jsonBackupNodeIds = jsonNode.get("backups").asArray();
113 if (jsonBackupNodeIds.size() != roleInfo.backups().size()) {
114 reason = "backup nodes size was " + jsonBackupNodeIds.size();
115 return false;
116 }
117
118 // check backup nodes' identifier
119 for (NodeId backupNodeId : roleInfo.backups()) {
120 boolean backupFound = false;
121 for (int idx = 0; idx < jsonBackupNodeIds.size(); idx++) {
122 if (backupNodeId.id().equals(jsonBackupNodeIds.get(idx).asString())) {
123 backupFound = true;
124 break;
125 }
126 }
127 if (!backupFound) {
128 reason = "backup not found " + backupNodeId.id();
129 return false;
130 }
131 }
132
133 return true;
134 }
135
136 @Override
137 public void describeTo(Description description) {
138 description.appendText(reason);
139 }
140 }
141
142 /**
143 * Factory to allocate a role info json matcher.
144 *
145 * @param roleInfo role info object we are looking for
146 * @return matcher
147 */
148 private static RoleInfoJsonMatcher matchesRoleInfo(RoleInfo roleInfo) {
149 return new RoleInfoJsonMatcher(roleInfo);
150 }
151
152 /**
153 * Sets up the global values for all the tests.
154 */
155 @Before
156 public void setUpTest() {
157
158 final CodecManager codecService = new CodecManager();
159 codecService.activate();
160 ServiceDirectory testDirectory =
161 new TestServiceDirectory()
162 .add(MastershipService.class, mockService)
163 .add(MastershipAdminService.class, mockAdminService)
164 .add(CodecService.class, codecService);
165
166 BaseResource.setServiceDirectory(testDirectory);
167 }
168
169 /**
170 * Tests the result of the REST API GET when there are active master roles.
171 */
172 @Test
173 public void testGetLocalRole() {
174 expect(mockService.getLocalRole(anyObject())).andReturn(role1).anyTimes();
175 replay(mockService);
176
177 final WebTarget wt = target();
178 final String response = wt.path("mastership/" + deviceId1.toString() +
179 "/local").request().get(String.class);
180 final JsonObject result = Json.parse(response).asObject();
181 assertThat(result, notNullValue());
182
183 assertThat(result.names(), hasSize(1));
184 assertThat(result.names().get(0), is("role"));
185
186 final String role = result.get("role").asString();
187 assertThat(role, notNullValue());
188 assertThat(role, is("MASTER"));
189 }
190
191 /**
192 * Tests the result of the REST API GET when there is no active master.
193 */
194 @Test
195 public void testGetMasterForNull() {
196 expect(mockService.getMasterFor(anyObject())).andReturn(null).anyTimes();
197 replay(mockService);
198
199 final WebTarget wt = target();
200 final Response response = wt.path("mastership/" + deviceId1.toString() +
201 "/master").request().get();
202 assertEquals(404, response.getStatus());
203 }
204
205 /**
206 * Tests the result of the REST API GET when there is active master.
207 */
208 @Test
209 public void testGetMasterFor() {
210 expect(mockService.getMasterFor(anyObject())).andReturn(nodeId1).anyTimes();
211 replay(mockService);
212
213 final WebTarget wt = target();
214 final String response = wt.path("mastership/" + deviceId1.toString() +
215 "/master").request().get(String.class);
216 final JsonObject result = Json.parse(response).asObject();
217 assertThat(result, notNullValue());
218
219 assertThat(result.names(), hasSize(1));
Jian Li0409b702016-05-03 18:21:37 -0700220 assertThat(result.names().get(0), is("nodeId"));
Jian Lif96d41f2016-05-03 09:49:12 -0700221
Jian Li0409b702016-05-03 18:21:37 -0700222 final String node = result.get("nodeId").asString();
Jian Lif96d41f2016-05-03 09:49:12 -0700223 assertThat(node, notNullValue());
224 assertThat(node, is("node:1"));
225 }
226
227 /**
228 * Tests the result of the REST API GET when there are no active nodes.
229 */
230 @Test
231 public void testGetNodesForNull() {
232 expect(mockService.getNodesFor(anyObject())).andReturn(null).anyTimes();
233 replay(mockService);
234
235 final WebTarget wt = target();
236 final Response response = wt.path("mastership/" + deviceId1.toString() +
237 "/role").request().get();
238 assertEquals(404, response.getStatus());
239 }
240
241 /**
242 * Tests the result of the REST API GET when there are active nodes.
243 */
244 @Test
245 public void testGetNodesFor() {
246 RoleInfo mockRoleInfo = createMockRoleInfo();
247 expect(mockService.getNodesFor(anyObject())).andReturn(mockRoleInfo).anyTimes();
248 replay(mockService);
249
250 final WebTarget wt = target();
251 final String response = wt.path("mastership/" + deviceId1.toString() +
252 "/role").request().get(String.class);
253 final JsonObject result = Json.parse(response).asObject();
254 assertThat(result, notNullValue());
255
256 assertThat(result, matchesRoleInfo(mockRoleInfo));
257 }
258
259 /**
260 * Tests the result of the REST API GET when there are active devices.
261 */
262 @Test
263 public void testGetDevicesOf() {
264 Set<DeviceId> deviceIds = ImmutableSet.of(deviceId1, deviceId2, deviceId3);
265 expect(mockService.getDevicesOf(anyObject())).andReturn(deviceIds).anyTimes();
266 replay(mockService);
267
268 final WebTarget wt = target();
269 final String response = wt.path("mastership/" + deviceId1.toString() +
270 "/device").request().get(String.class);
271 final JsonObject result = Json.parse(response).asObject();
272 assertThat(result, notNullValue());
273
274 assertThat(result.names(), hasSize(1));
Jian Li0409b702016-05-03 18:21:37 -0700275 assertThat(result.names().get(0), is("deviceIds"));
Jian Lif96d41f2016-05-03 09:49:12 -0700276
Jian Li0409b702016-05-03 18:21:37 -0700277 final JsonArray jsonDevices = result.get("deviceIds").asArray();
Jian Lif96d41f2016-05-03 09:49:12 -0700278 assertThat(jsonDevices, notNullValue());
279 assertThat(jsonDevices.size(), is(3));
280 }
281
282 /**
283 * Tests the result of the REST API GET for requesting mastership role.
284 */
285 @Test
286 public void testRequestRoleFor() {
Jian Li0409b702016-05-03 18:21:37 -0700287 expect(mockService.requestRoleForSync(anyObject())).andReturn(role1).anyTimes();
288 replay(mockService);
289
290 final WebTarget wt = target();
291 final String response = wt.path("mastership/" + deviceId1.toString() +
292 "/request").request().get(String.class);
293 final JsonObject result = Json.parse(response).asObject();
294 assertThat(result, notNullValue());
295
296 assertThat(result.names(), hasSize(1));
297 assertThat(result.names().get(0), is("role"));
298
299 final String role = result.get("role").asString();
300 assertThat(role, notNullValue());
301 assertThat(role, is("MASTER"));
Jian Lif96d41f2016-05-03 09:49:12 -0700302 }
303
304 /**
305 * Tests the result of the REST API GET for relinquishing mastership role.
306 */
307 @Test
308 public void testRelinquishMastership() {
Jian Li0409b702016-05-03 18:21:37 -0700309 mockService.relinquishMastershipSync(anyObject());
310 expectLastCall();
311 replay(mockService);
312
313 final WebTarget wt = target();
314 final Response response = wt.path("mastership/" + deviceId1.toString() +
315 "/relinquish").request().get();
316 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
317 String location = response.getLocation().toString();
318 assertThat(location, Matchers.startsWith(deviceId1.toString()));
Jian Lif96d41f2016-05-03 09:49:12 -0700319 }
320
321 /**
322 * Tests the result of the REST API PUT for setting role.
323 */
324 @Test
325 public void testSetRole() {
Jian Li0409b702016-05-03 18:21:37 -0700326 mockAdminService.setRoleSync(anyObject(), anyObject(), anyObject());
327 expectLastCall();
328 replay(mockAdminService);
329
330 final WebTarget wt = target();
331 final InputStream jsonStream = MetersResourceTest.class
332 .getResourceAsStream("put-set-roles.json");
333 final Response response = wt.path("mastership")
334 .request().put(Entity.json(jsonStream));
335 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
Jian Lif96d41f2016-05-03 09:49:12 -0700336 }
337
338 /**
339 * Tests the result of the REST API GET for balancing roles.
340 */
341 @Test
342 public void testBalanceRoles() {
343 mockAdminService.balanceRoles();
344 expectLastCall();
345 replay(mockAdminService);
346
347 final WebTarget wt = target();
348 final Response response = wt.path("mastership").request().get();
349 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
350 }
351}