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