blob: 0c8e5c5059bce9cc0f22d870ee31b39c5f4a77b9 [file] [log] [blame]
Madan Jampani5e5b3d62016-02-01 16:03:33 -08001/*
2 * Copyright 2016 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.store.primitives.resources.impl;
17
18import java.util.LinkedList;
19import java.util.Queue;
20import java.util.concurrent.CompletableFuture;
21import java.util.function.Consumer;
22
Madan Jampani07b54482016-03-09 10:34:18 -080023import org.junit.Ignore;
Madan Jampani5e5b3d62016-02-01 16:03:33 -080024import org.junit.Test;
25
26import static org.junit.Assert.*;
27
28import org.onosproject.cluster.Leadership;
29import org.onosproject.cluster.NodeId;
30import org.onosproject.event.Change;
31
32import io.atomix.Atomix;
33import io.atomix.resource.ResourceType;
34
35/**
36 * Unit tests for {@link AtomixLeaderElector}.
37 */
Madan Jampani07b54482016-03-09 10:34:18 -080038@Ignore
Madan Jampani5e5b3d62016-02-01 16:03:33 -080039public class AtomixLeaderElectorTest extends AtomixTestBase {
40
41 NodeId node1 = new NodeId("node1");
42 NodeId node2 = new NodeId("node2");
43 NodeId node3 = new NodeId("node3");
44
45 @Override
46 protected ResourceType resourceType() {
47 return new ResourceType(AtomixLeaderElector.class);
48 }
49
50 @Test
51 public void testRun() throws Throwable {
52 leaderElectorRunTests(1);
53 clearTests();
Madan Jampani0c0cdc62016-02-22 16:54:06 -080054 leaderElectorRunTests(2);
55 clearTests();
56 leaderElectorRunTests(3);
57 clearTests();
Madan Jampani5e5b3d62016-02-01 16:03:33 -080058 }
59
60 private void leaderElectorRunTests(int numServers) throws Throwable {
61 createCopycatServers(numServers);
62 Atomix client1 = createAtomixClient();
Madan Jampani65f24bb2016-03-15 15:16:18 -070063 AtomixLeaderElector elector1 = client1.getResource("test-elector", AtomixLeaderElector.class).join();
Madan Jampani5e5b3d62016-02-01 16:03:33 -080064 elector1.run("foo", node1).thenAccept(result -> {
65 assertEquals(node1, result.leaderNodeId());
66 assertEquals(1, result.leader().term());
67 assertEquals(1, result.candidates().size());
68 assertEquals(node1, result.candidates().get(0));
69 }).join();
70 Atomix client2 = createAtomixClient();
Madan Jampani65f24bb2016-03-15 15:16:18 -070071 AtomixLeaderElector elector2 = client2.getResource("test-elector", AtomixLeaderElector.class).join();
Madan Jampani5e5b3d62016-02-01 16:03:33 -080072 elector2.run("foo", node2).thenAccept(result -> {
73 assertEquals(node1, result.leaderNodeId());
74 assertEquals(1, result.leader().term());
75 assertEquals(2, result.candidates().size());
76 assertEquals(node1, result.candidates().get(0));
77 assertEquals(node2, result.candidates().get(1));
78 }).join();
79 }
80
81 @Test
82 public void testWithdraw() throws Throwable {
83 leaderElectorWithdrawTests(1);
84 clearTests();
85 leaderElectorWithdrawTests(2);
86 clearTests();
87 leaderElectorWithdrawTests(3);
88 clearTests();
89 }
90
91 private void leaderElectorWithdrawTests(int numServers) throws Throwable {
92 createCopycatServers(numServers);
93 Atomix client1 = createAtomixClient();
Madan Jampani65f24bb2016-03-15 15:16:18 -070094 AtomixLeaderElector elector1 = client1.getResource("test-elector", AtomixLeaderElector.class).join();
Madan Jampani5e5b3d62016-02-01 16:03:33 -080095 elector1.run("foo", node1).join();
96 Atomix client2 = createAtomixClient();
Madan Jampani65f24bb2016-03-15 15:16:18 -070097 AtomixLeaderElector elector2 = client2.getResource("test-elector", AtomixLeaderElector.class).join();
Madan Jampani5e5b3d62016-02-01 16:03:33 -080098 elector2.run("foo", node2).join();
99
100 LeaderEventListener listener1 = new LeaderEventListener();
101 elector1.addChangeListener(listener1).join();
102
103 LeaderEventListener listener2 = new LeaderEventListener();
104 elector2.addChangeListener(listener2).join();
105
106 elector1.withdraw("foo").join();
107
108 listener1.nextEvent().thenAccept(result -> {
109 assertEquals(node2, result.newValue().leaderNodeId());
110 assertEquals(2, result.newValue().leader().term());
111 assertEquals(1, result.newValue().candidates().size());
112 assertEquals(node2, result.newValue().candidates().get(0));
113 }).join();
114
115 listener2.nextEvent().thenAccept(result -> {
116 assertEquals(node2, result.newValue().leaderNodeId());
117 assertEquals(2, result.newValue().leader().term());
118 assertEquals(1, result.newValue().candidates().size());
119 assertEquals(node2, result.newValue().candidates().get(0));
120 }).join();
121 }
122
123 @Test
124 public void testAnoint() throws Throwable {
125 leaderElectorAnointTests(1);
126 clearTests();
127 leaderElectorAnointTests(2);
128 clearTests();
129 leaderElectorAnointTests(3);
130 clearTests();
131 }
132
133 private void leaderElectorAnointTests(int numServers) throws Throwable {
134 createCopycatServers(numServers);
135 Atomix client1 = createAtomixClient();
Madan Jampani65f24bb2016-03-15 15:16:18 -0700136 AtomixLeaderElector elector1 = client1.getResource("test-elector", AtomixLeaderElector.class).join();
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800137 Atomix client2 = createAtomixClient();
Madan Jampani65f24bb2016-03-15 15:16:18 -0700138 AtomixLeaderElector elector2 = client2.getResource("test-elector", AtomixLeaderElector.class).join();
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800139 Atomix client3 = createAtomixClient();
Madan Jampani65f24bb2016-03-15 15:16:18 -0700140 AtomixLeaderElector elector3 = client3.getResource("test-elector", AtomixLeaderElector.class).join();
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800141 elector1.run("foo", node1).join();
142 elector2.run("foo", node2).join();
143
144 LeaderEventListener listener1 = new LeaderEventListener();
145 elector1.addChangeListener(listener1).join();
146 LeaderEventListener listener2 = new LeaderEventListener();
147 elector2.addChangeListener(listener2);
148 LeaderEventListener listener3 = new LeaderEventListener();
149 elector3.addChangeListener(listener3).join();
150
151 elector3.anoint("foo", node3).thenAccept(result -> {
152 assertFalse(result);
153 }).join();
154 assertFalse(listener1.hasEvent());
155 assertFalse(listener2.hasEvent());
156 assertFalse(listener3.hasEvent());
157
158 elector3.anoint("foo", node2).thenAccept(result -> {
159 assertTrue(result);
160 }).join();
161 assertTrue(listener1.hasEvent());
162 assertTrue(listener2.hasEvent());
163 assertTrue(listener3.hasEvent());
164
165 listener1.nextEvent().thenAccept(result -> {
166 assertEquals(node2, result.newValue().leaderNodeId());
167 assertEquals(2, result.newValue().candidates().size());
168 assertEquals(node1, result.newValue().candidates().get(0));
169 assertEquals(node2, result.newValue().candidates().get(1));
170 }).join();
171 listener2.nextEvent().thenAccept(result -> {
172 assertEquals(node2, result.newValue().leaderNodeId());
173 assertEquals(2, result.newValue().candidates().size());
174 assertEquals(node1, result.newValue().candidates().get(0));
175 assertEquals(node2, result.newValue().candidates().get(1));
176 }).join();
177 listener3.nextEvent().thenAccept(result -> {
178 assertEquals(node2, result.newValue().leaderNodeId());
179 assertEquals(2, result.newValue().candidates().size());
180 assertEquals(node1, result.newValue().candidates().get(0));
181 assertEquals(node2, result.newValue().candidates().get(1));
182 }).join();
183 }
184
185 @Test
Madan Jampani0c0cdc62016-02-22 16:54:06 -0800186 public void testPromote() throws Throwable {
187 leaderElectorPromoteTests(1);
188 clearTests();
189 leaderElectorPromoteTests(2);
190 clearTests();
191 leaderElectorPromoteTests(3);
192 clearTests();
193 }
194
195 private void leaderElectorPromoteTests(int numServers) throws Throwable {
196 createCopycatServers(numServers);
197 Atomix client1 = createAtomixClient();
Madan Jampani65f24bb2016-03-15 15:16:18 -0700198 AtomixLeaderElector elector1 = client1.getResource("test-elector", AtomixLeaderElector.class).join();
Madan Jampani0c0cdc62016-02-22 16:54:06 -0800199 Atomix client2 = createAtomixClient();
Madan Jampani65f24bb2016-03-15 15:16:18 -0700200 AtomixLeaderElector elector2 = client2.getResource("test-elector", AtomixLeaderElector.class).join();
Madan Jampani0c0cdc62016-02-22 16:54:06 -0800201 Atomix client3 = createAtomixClient();
Madan Jampani65f24bb2016-03-15 15:16:18 -0700202 AtomixLeaderElector elector3 = client3.getResource("test-elector", AtomixLeaderElector.class).join();
Madan Jampani0c0cdc62016-02-22 16:54:06 -0800203 elector1.run("foo", node1).join();
204 elector2.run("foo", node2).join();
205
206 LeaderEventListener listener1 = new LeaderEventListener();
207 elector1.addChangeListener(listener1).join();
208 LeaderEventListener listener2 = new LeaderEventListener();
209 elector2.addChangeListener(listener2).join();
210 LeaderEventListener listener3 = new LeaderEventListener();
211 elector3.addChangeListener(listener3).join();
212
213 elector3.promote("foo", node3).thenAccept(result -> {
214 assertFalse(result);
215 }).join();
216
217 assertFalse(listener1.hasEvent());
218 assertFalse(listener2.hasEvent());
219 assertFalse(listener3.hasEvent());
220
221 elector3.run("foo", node3).join();
222
223 listener1.clearEvents();
224 listener2.clearEvents();
225 listener3.clearEvents();
226
227 elector3.promote("foo", node3).thenAccept(result -> {
228 assertTrue(result);
229 }).join();
230
231 listener1.nextEvent().thenAccept(result -> {
232 assertEquals(node3, result.newValue().candidates().get(0));
233 }).join();
234 listener2.nextEvent().thenAccept(result -> {
235 assertEquals(node3, result.newValue().candidates().get(0));
236 }).join();
237 listener3.nextEvent().thenAccept(result -> {
238 assertEquals(node3, result.newValue().candidates().get(0));
239 }).join();
240 }
241
242 @Test
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800243 public void testLeaderSessionClose() throws Throwable {
244 leaderElectorLeaderSessionCloseTests(1);
245 clearTests();
246 leaderElectorLeaderSessionCloseTests(2);
247 clearTests();
248 leaderElectorLeaderSessionCloseTests(3);
249 clearTests();
250 }
251
252 private void leaderElectorLeaderSessionCloseTests(int numServers) throws Throwable {
253 createCopycatServers(numServers);
254 Atomix client1 = createAtomixClient();
Madan Jampani65f24bb2016-03-15 15:16:18 -0700255 AtomixLeaderElector elector1 = client1.getResource("test-elector", AtomixLeaderElector.class).join();
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800256 elector1.run("foo", node1).join();
257 Atomix client2 = createAtomixClient();
Madan Jampani65f24bb2016-03-15 15:16:18 -0700258 AtomixLeaderElector elector2 = client2.getResource("test-elector", AtomixLeaderElector.class).join();
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800259 LeaderEventListener listener = new LeaderEventListener();
260 elector2.run("foo", node2).join();
261 elector2.addChangeListener(listener).join();
262 client1.close();
263 listener.nextEvent().thenAccept(result -> {
264 assertEquals(node2, result.newValue().leaderNodeId());
265 assertEquals(1, result.newValue().candidates().size());
266 assertEquals(node2, result.newValue().candidates().get(0));
267 }).join();
268 }
269
270 @Test
271 public void testNonLeaderSessionClose() throws Throwable {
272 leaderElectorNonLeaderSessionCloseTests(1);
273 clearTests();
274 leaderElectorNonLeaderSessionCloseTests(2);
275 clearTests();
276 leaderElectorNonLeaderSessionCloseTests(3);
277 clearTests();
278 }
279
280 private void leaderElectorNonLeaderSessionCloseTests(int numServers) throws Throwable {
281 createCopycatServers(numServers);
282 Atomix client1 = createAtomixClient();
Madan Jampani65f24bb2016-03-15 15:16:18 -0700283 AtomixLeaderElector elector1 = client1.getResource("test-elector", AtomixLeaderElector.class).join();
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800284 elector1.run("foo", node1).join();
285 Atomix client2 = createAtomixClient();
Madan Jampani65f24bb2016-03-15 15:16:18 -0700286 AtomixLeaderElector elector2 = client2.getResource("test-elector", AtomixLeaderElector.class).join();
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800287 LeaderEventListener listener = new LeaderEventListener();
288 elector2.run("foo", node2).join();
289 elector1.addChangeListener(listener).join();
290 client2.close().join();
291 listener.nextEvent().thenAccept(result -> {
292 assertEquals(node1, result.newValue().leaderNodeId());
293 assertEquals(1, result.newValue().candidates().size());
294 assertEquals(node1, result.newValue().candidates().get(0));
295 }).join();
296 }
297
298 @Test
299 public void testQueries() throws Throwable {
300 leaderElectorQueryTests(1);
301 clearTests();
302 leaderElectorQueryTests(2);
303 clearTests();
304 leaderElectorQueryTests(3);
305 clearTests();
306 }
307
308 private void leaderElectorQueryTests(int numServers) throws Throwable {
309 createCopycatServers(numServers);
310 Atomix client1 = createAtomixClient();
311 Atomix client2 = createAtomixClient();
Madan Jampani65f24bb2016-03-15 15:16:18 -0700312 AtomixLeaderElector elector1 = client1.getResource("test-elector", AtomixLeaderElector.class).join();
313 AtomixLeaderElector elector2 = client2.getResource("test-elector", AtomixLeaderElector.class).join();
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800314 elector1.run("foo", node1).join();
315 elector2.run("foo", node2).join();
316 elector2.run("bar", node2).join();
317 elector1.getElectedTopics(node1).thenAccept(result -> {
318 assertEquals(1, result.size());
319 assertTrue(result.contains("foo"));
320 }).join();
321 elector2.getElectedTopics(node1).thenAccept(result -> {
322 assertEquals(1, result.size());
323 assertTrue(result.contains("foo"));
324 }).join();
325 elector1.getLeadership("foo").thenAccept(result -> {
326 assertEquals(node1, result.leaderNodeId());
327 assertEquals(node1, result.candidates().get(0));
328 assertEquals(node2, result.candidates().get(1));
329 }).join();
330 elector2.getLeadership("foo").thenAccept(result -> {
331 assertEquals(node1, result.leaderNodeId());
332 assertEquals(node1, result.candidates().get(0));
333 assertEquals(node2, result.candidates().get(1));
334 }).join();
335 elector1.getLeadership("bar").thenAccept(result -> {
336 assertEquals(node2, result.leaderNodeId());
337 assertEquals(node2, result.candidates().get(0));
338 }).join();
339 elector2.getLeadership("bar").thenAccept(result -> {
340 assertEquals(node2, result.leaderNodeId());
341 assertEquals(node2, result.candidates().get(0));
342 }).join();
343 elector1.getLeaderships().thenAccept(result -> {
344 assertEquals(2, result.size());
345 Leadership fooLeadership = result.get("foo");
346 assertEquals(node1, fooLeadership.leaderNodeId());
347 assertEquals(node1, fooLeadership.candidates().get(0));
348 assertEquals(node2, fooLeadership.candidates().get(1));
349 Leadership barLeadership = result.get("bar");
350 assertEquals(node2, barLeadership.leaderNodeId());
351 assertEquals(node2, barLeadership.candidates().get(0));
352 }).join();
353 elector2.getLeaderships().thenAccept(result -> {
354 assertEquals(2, result.size());
355 Leadership fooLeadership = result.get("foo");
356 assertEquals(node1, fooLeadership.leaderNodeId());
357 assertEquals(node1, fooLeadership.candidates().get(0));
358 assertEquals(node2, fooLeadership.candidates().get(1));
359 Leadership barLeadership = result.get("bar");
360 assertEquals(node2, barLeadership.leaderNodeId());
361 assertEquals(node2, barLeadership.candidates().get(0));
362 }).join();
363 }
364
365 private static class LeaderEventListener implements Consumer<Change<Leadership>> {
366 Queue<Change<Leadership>> eventQueue = new LinkedList<>();
367 CompletableFuture<Change<Leadership>> pendingFuture;
368
369 @Override
370 public void accept(Change<Leadership> change) {
371 synchronized (this) {
372 if (pendingFuture != null) {
373 pendingFuture.complete(change);
374 pendingFuture = null;
375 } else {
376 eventQueue.add(change);
377 }
378 }
379 }
380
381 public boolean hasEvent() {
382 return !eventQueue.isEmpty();
383 }
384
Madan Jampani0c0cdc62016-02-22 16:54:06 -0800385 public void clearEvents() {
386 eventQueue.clear();
387 }
388
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800389 public CompletableFuture<Change<Leadership>> nextEvent() {
390 synchronized (this) {
391 if (eventQueue.isEmpty()) {
392 if (pendingFuture == null) {
393 pendingFuture = new CompletableFuture<>();
394 }
395 return pendingFuture;
396 } else {
397 return CompletableFuture.completedFuture(eventQueue.poll());
398 }
399 }
400 }
401 }
402}