blob: 6fb064bec3cb50b034a0bbaba208209ff5cb6e02 [file] [log] [blame]
Madan Jampani5e5b3d62016-02-01 16:03:33 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
Madan Jampani5e5b3d62016-02-01 16:03:33 -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.store.primitives.resources.impl;
17
18import java.util.LinkedList;
19import java.util.Queue;
20import java.util.concurrent.CompletableFuture;
21import java.util.function.Consumer;
22
Aaron Kruglikov5bb38122016-06-22 12:07:23 -070023import 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;
Madan Jampani630e7ac2016-05-31 11:34:05 -070033import io.atomix.AtomixClient;
Madan Jampani5e5b3d62016-02-01 16:03:33 -080034import io.atomix.resource.ResourceType;
35
36/**
37 * Unit tests for {@link AtomixLeaderElector}.
38 */
Aaron Kruglikov5bb38122016-06-22 12:07:23 -070039@Ignore
Madan Jampani5e5b3d62016-02-01 16:03:33 -080040public class AtomixLeaderElectorTest extends AtomixTestBase {
41
42 NodeId node1 = new NodeId("node1");
43 NodeId node2 = new NodeId("node2");
44 NodeId node3 = new NodeId("node3");
45
46 @Override
47 protected ResourceType resourceType() {
48 return new ResourceType(AtomixLeaderElector.class);
49 }
50
51 @Test
52 public void testRun() throws Throwable {
Madan Jampani0c0cdc62016-02-22 16:54:06 -080053 leaderElectorRunTests(3);
Madan Jampani5e5b3d62016-02-01 16:03:33 -080054 }
55
56 private void leaderElectorRunTests(int numServers) throws Throwable {
57 createCopycatServers(numServers);
58 Atomix client1 = createAtomixClient();
Madan Jampani65f24bb2016-03-15 15:16:18 -070059 AtomixLeaderElector elector1 = client1.getResource("test-elector", AtomixLeaderElector.class).join();
Madan Jampani5e5b3d62016-02-01 16:03:33 -080060 elector1.run("foo", node1).thenAccept(result -> {
61 assertEquals(node1, result.leaderNodeId());
62 assertEquals(1, result.leader().term());
63 assertEquals(1, result.candidates().size());
64 assertEquals(node1, result.candidates().get(0));
65 }).join();
66 Atomix client2 = createAtomixClient();
Madan Jampani65f24bb2016-03-15 15:16:18 -070067 AtomixLeaderElector elector2 = client2.getResource("test-elector", AtomixLeaderElector.class).join();
Madan Jampani5e5b3d62016-02-01 16:03:33 -080068 elector2.run("foo", node2).thenAccept(result -> {
69 assertEquals(node1, result.leaderNodeId());
70 assertEquals(1, result.leader().term());
71 assertEquals(2, result.candidates().size());
72 assertEquals(node1, result.candidates().get(0));
73 assertEquals(node2, result.candidates().get(1));
74 }).join();
75 }
76
77 @Test
78 public void testWithdraw() throws Throwable {
Madan Jampani5e5b3d62016-02-01 16:03:33 -080079 leaderElectorWithdrawTests(3);
Madan Jampani5e5b3d62016-02-01 16:03:33 -080080 }
81
82 private void leaderElectorWithdrawTests(int numServers) throws Throwable {
83 createCopycatServers(numServers);
84 Atomix client1 = createAtomixClient();
Madan Jampani65f24bb2016-03-15 15:16:18 -070085 AtomixLeaderElector elector1 = client1.getResource("test-elector", AtomixLeaderElector.class).join();
Madan Jampani5e5b3d62016-02-01 16:03:33 -080086 elector1.run("foo", node1).join();
87 Atomix client2 = createAtomixClient();
Madan Jampani65f24bb2016-03-15 15:16:18 -070088 AtomixLeaderElector elector2 = client2.getResource("test-elector", AtomixLeaderElector.class).join();
Madan Jampani5e5b3d62016-02-01 16:03:33 -080089 elector2.run("foo", node2).join();
90
91 LeaderEventListener listener1 = new LeaderEventListener();
92 elector1.addChangeListener(listener1).join();
93
94 LeaderEventListener listener2 = new LeaderEventListener();
95 elector2.addChangeListener(listener2).join();
96
97 elector1.withdraw("foo").join();
98
99 listener1.nextEvent().thenAccept(result -> {
100 assertEquals(node2, result.newValue().leaderNodeId());
101 assertEquals(2, result.newValue().leader().term());
102 assertEquals(1, result.newValue().candidates().size());
103 assertEquals(node2, result.newValue().candidates().get(0));
104 }).join();
105
106 listener2.nextEvent().thenAccept(result -> {
107 assertEquals(node2, result.newValue().leaderNodeId());
108 assertEquals(2, result.newValue().leader().term());
109 assertEquals(1, result.newValue().candidates().size());
110 assertEquals(node2, result.newValue().candidates().get(0));
111 }).join();
112 }
113
114 @Test
115 public void testAnoint() throws Throwable {
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800116 leaderElectorAnointTests(3);
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800117 }
118
119 private void leaderElectorAnointTests(int numServers) throws Throwable {
120 createCopycatServers(numServers);
121 Atomix client1 = createAtomixClient();
Madan Jampani65f24bb2016-03-15 15:16:18 -0700122 AtomixLeaderElector elector1 = client1.getResource("test-elector", AtomixLeaderElector.class).join();
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800123 Atomix client2 = createAtomixClient();
Madan Jampani65f24bb2016-03-15 15:16:18 -0700124 AtomixLeaderElector elector2 = client2.getResource("test-elector", AtomixLeaderElector.class).join();
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800125 Atomix client3 = createAtomixClient();
Madan Jampani65f24bb2016-03-15 15:16:18 -0700126 AtomixLeaderElector elector3 = client3.getResource("test-elector", AtomixLeaderElector.class).join();
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800127 elector1.run("foo", node1).join();
128 elector2.run("foo", node2).join();
129
130 LeaderEventListener listener1 = new LeaderEventListener();
131 elector1.addChangeListener(listener1).join();
132 LeaderEventListener listener2 = new LeaderEventListener();
133 elector2.addChangeListener(listener2);
134 LeaderEventListener listener3 = new LeaderEventListener();
135 elector3.addChangeListener(listener3).join();
136
137 elector3.anoint("foo", node3).thenAccept(result -> {
138 assertFalse(result);
139 }).join();
140 assertFalse(listener1.hasEvent());
141 assertFalse(listener2.hasEvent());
142 assertFalse(listener3.hasEvent());
143
144 elector3.anoint("foo", node2).thenAccept(result -> {
145 assertTrue(result);
146 }).join();
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800147
148 listener1.nextEvent().thenAccept(result -> {
149 assertEquals(node2, result.newValue().leaderNodeId());
150 assertEquals(2, result.newValue().candidates().size());
151 assertEquals(node1, result.newValue().candidates().get(0));
152 assertEquals(node2, result.newValue().candidates().get(1));
153 }).join();
154 listener2.nextEvent().thenAccept(result -> {
155 assertEquals(node2, result.newValue().leaderNodeId());
156 assertEquals(2, result.newValue().candidates().size());
157 assertEquals(node1, result.newValue().candidates().get(0));
158 assertEquals(node2, result.newValue().candidates().get(1));
159 }).join();
160 listener3.nextEvent().thenAccept(result -> {
161 assertEquals(node2, result.newValue().leaderNodeId());
162 assertEquals(2, result.newValue().candidates().size());
163 assertEquals(node1, result.newValue().candidates().get(0));
164 assertEquals(node2, result.newValue().candidates().get(1));
165 }).join();
166 }
167
168 @Test
Madan Jampani0c0cdc62016-02-22 16:54:06 -0800169 public void testPromote() throws Throwable {
Madan Jampani0c0cdc62016-02-22 16:54:06 -0800170 leaderElectorPromoteTests(3);
Madan Jampani0c0cdc62016-02-22 16:54:06 -0800171 }
172
173 private void leaderElectorPromoteTests(int numServers) throws Throwable {
174 createCopycatServers(numServers);
Madan Jampani630e7ac2016-05-31 11:34:05 -0700175 AtomixClient client1 = createAtomixClient();
Madan Jampani65f24bb2016-03-15 15:16:18 -0700176 AtomixLeaderElector elector1 = client1.getResource("test-elector", AtomixLeaderElector.class).join();
Madan Jampani630e7ac2016-05-31 11:34:05 -0700177 AtomixClient client2 = createAtomixClient();
Madan Jampani65f24bb2016-03-15 15:16:18 -0700178 AtomixLeaderElector elector2 = client2.getResource("test-elector", AtomixLeaderElector.class).join();
Madan Jampani630e7ac2016-05-31 11:34:05 -0700179 AtomixClient client3 = createAtomixClient();
Madan Jampani65f24bb2016-03-15 15:16:18 -0700180 AtomixLeaderElector elector3 = client3.getResource("test-elector", AtomixLeaderElector.class).join();
Madan Jampani0c0cdc62016-02-22 16:54:06 -0800181 elector1.run("foo", node1).join();
182 elector2.run("foo", node2).join();
183
184 LeaderEventListener listener1 = new LeaderEventListener();
185 elector1.addChangeListener(listener1).join();
186 LeaderEventListener listener2 = new LeaderEventListener();
187 elector2.addChangeListener(listener2).join();
188 LeaderEventListener listener3 = new LeaderEventListener();
189 elector3.addChangeListener(listener3).join();
190
191 elector3.promote("foo", node3).thenAccept(result -> {
192 assertFalse(result);
193 }).join();
194
195 assertFalse(listener1.hasEvent());
196 assertFalse(listener2.hasEvent());
197 assertFalse(listener3.hasEvent());
198
199 elector3.run("foo", node3).join();
200
Madan Jampani630e7ac2016-05-31 11:34:05 -0700201 listener1.nextEvent().thenAccept(result -> {
202 assertEquals(node3, result.newValue().candidates().get(2));
203 }).join();
204 listener2.nextEvent().thenAccept(result -> {
205 assertEquals(node3, result.newValue().candidates().get(2));
206 }).join();
207 listener3.nextEvent().thenAccept(result -> {
208 assertEquals(node3, result.newValue().candidates().get(2));
209 }).join();
Madan Jampani0c0cdc62016-02-22 16:54:06 -0800210
211 elector3.promote("foo", node3).thenAccept(result -> {
212 assertTrue(result);
213 }).join();
214
215 listener1.nextEvent().thenAccept(result -> {
216 assertEquals(node3, result.newValue().candidates().get(0));
217 }).join();
218 listener2.nextEvent().thenAccept(result -> {
219 assertEquals(node3, result.newValue().candidates().get(0));
220 }).join();
221 listener3.nextEvent().thenAccept(result -> {
222 assertEquals(node3, result.newValue().candidates().get(0));
223 }).join();
224 }
225
226 @Test
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800227 public void testLeaderSessionClose() throws Throwable {
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800228 leaderElectorLeaderSessionCloseTests(3);
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800229 }
230
231 private void leaderElectorLeaderSessionCloseTests(int numServers) throws Throwable {
232 createCopycatServers(numServers);
Madan Jampani630e7ac2016-05-31 11:34:05 -0700233 AtomixClient client1 = createAtomixClient();
Madan Jampani65f24bb2016-03-15 15:16:18 -0700234 AtomixLeaderElector elector1 = client1.getResource("test-elector", AtomixLeaderElector.class).join();
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800235 elector1.run("foo", node1).join();
236 Atomix client2 = createAtomixClient();
Madan Jampani65f24bb2016-03-15 15:16:18 -0700237 AtomixLeaderElector elector2 = client2.getResource("test-elector", AtomixLeaderElector.class).join();
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800238 LeaderEventListener listener = new LeaderEventListener();
239 elector2.run("foo", node2).join();
240 elector2.addChangeListener(listener).join();
241 client1.close();
242 listener.nextEvent().thenAccept(result -> {
243 assertEquals(node2, result.newValue().leaderNodeId());
244 assertEquals(1, result.newValue().candidates().size());
245 assertEquals(node2, result.newValue().candidates().get(0));
246 }).join();
247 }
248
249 @Test
250 public void testNonLeaderSessionClose() throws Throwable {
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800251 leaderElectorNonLeaderSessionCloseTests(3);
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800252 }
253
254 private void leaderElectorNonLeaderSessionCloseTests(int numServers) throws Throwable {
255 createCopycatServers(numServers);
256 Atomix client1 = createAtomixClient();
Madan Jampani65f24bb2016-03-15 15:16:18 -0700257 AtomixLeaderElector elector1 = client1.getResource("test-elector", AtomixLeaderElector.class).join();
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800258 elector1.run("foo", node1).join();
Madan Jampani630e7ac2016-05-31 11:34:05 -0700259 AtomixClient client2 = createAtomixClient();
Madan Jampani65f24bb2016-03-15 15:16:18 -0700260 AtomixLeaderElector elector2 = client2.getResource("test-elector", AtomixLeaderElector.class).join();
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800261 LeaderEventListener listener = new LeaderEventListener();
262 elector2.run("foo", node2).join();
263 elector1.addChangeListener(listener).join();
264 client2.close().join();
265 listener.nextEvent().thenAccept(result -> {
266 assertEquals(node1, result.newValue().leaderNodeId());
267 assertEquals(1, result.newValue().candidates().size());
268 assertEquals(node1, result.newValue().candidates().get(0));
269 }).join();
270 }
271
272 @Test
273 public void testQueries() throws Throwable {
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800274 leaderElectorQueryTests(3);
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800275 }
276
277 private void leaderElectorQueryTests(int numServers) throws Throwable {
278 createCopycatServers(numServers);
279 Atomix client1 = createAtomixClient();
280 Atomix client2 = createAtomixClient();
Madan Jampani65f24bb2016-03-15 15:16:18 -0700281 AtomixLeaderElector elector1 = client1.getResource("test-elector", AtomixLeaderElector.class).join();
282 AtomixLeaderElector elector2 = client2.getResource("test-elector", AtomixLeaderElector.class).join();
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800283 elector1.run("foo", node1).join();
284 elector2.run("foo", node2).join();
285 elector2.run("bar", node2).join();
286 elector1.getElectedTopics(node1).thenAccept(result -> {
287 assertEquals(1, result.size());
288 assertTrue(result.contains("foo"));
289 }).join();
290 elector2.getElectedTopics(node1).thenAccept(result -> {
291 assertEquals(1, result.size());
292 assertTrue(result.contains("foo"));
293 }).join();
294 elector1.getLeadership("foo").thenAccept(result -> {
295 assertEquals(node1, result.leaderNodeId());
296 assertEquals(node1, result.candidates().get(0));
297 assertEquals(node2, result.candidates().get(1));
298 }).join();
299 elector2.getLeadership("foo").thenAccept(result -> {
300 assertEquals(node1, result.leaderNodeId());
301 assertEquals(node1, result.candidates().get(0));
302 assertEquals(node2, result.candidates().get(1));
303 }).join();
304 elector1.getLeadership("bar").thenAccept(result -> {
305 assertEquals(node2, result.leaderNodeId());
306 assertEquals(node2, result.candidates().get(0));
307 }).join();
308 elector2.getLeadership("bar").thenAccept(result -> {
309 assertEquals(node2, result.leaderNodeId());
310 assertEquals(node2, result.candidates().get(0));
311 }).join();
312 elector1.getLeaderships().thenAccept(result -> {
313 assertEquals(2, result.size());
314 Leadership fooLeadership = result.get("foo");
315 assertEquals(node1, fooLeadership.leaderNodeId());
316 assertEquals(node1, fooLeadership.candidates().get(0));
317 assertEquals(node2, fooLeadership.candidates().get(1));
318 Leadership barLeadership = result.get("bar");
319 assertEquals(node2, barLeadership.leaderNodeId());
320 assertEquals(node2, barLeadership.candidates().get(0));
321 }).join();
322 elector2.getLeaderships().thenAccept(result -> {
323 assertEquals(2, result.size());
324 Leadership fooLeadership = result.get("foo");
325 assertEquals(node1, fooLeadership.leaderNodeId());
326 assertEquals(node1, fooLeadership.candidates().get(0));
327 assertEquals(node2, fooLeadership.candidates().get(1));
328 Leadership barLeadership = result.get("bar");
329 assertEquals(node2, barLeadership.leaderNodeId());
330 assertEquals(node2, barLeadership.candidates().get(0));
331 }).join();
332 }
333
334 private static class LeaderEventListener implements Consumer<Change<Leadership>> {
335 Queue<Change<Leadership>> eventQueue = new LinkedList<>();
336 CompletableFuture<Change<Leadership>> pendingFuture;
337
338 @Override
339 public void accept(Change<Leadership> change) {
340 synchronized (this) {
341 if (pendingFuture != null) {
342 pendingFuture.complete(change);
343 pendingFuture = null;
344 } else {
345 eventQueue.add(change);
346 }
347 }
348 }
349
350 public boolean hasEvent() {
351 return !eventQueue.isEmpty();
352 }
353
Madan Jampani0c0cdc62016-02-22 16:54:06 -0800354 public void clearEvents() {
355 eventQueue.clear();
356 }
357
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800358 public CompletableFuture<Change<Leadership>> nextEvent() {
359 synchronized (this) {
360 if (eventQueue.isEmpty()) {
361 if (pendingFuture == null) {
362 pendingFuture = new CompletableFuture<>();
363 }
364 return pendingFuture;
365 } else {
366 return CompletableFuture.completedFuture(eventQueue.poll());
367 }
368 }
369 }
370 }
371}