AsyncLeaderElector APIs in support for mastership balancing

Change-Id: Ia235c6a18c54490dc49ca13e2caebf70b750dbc7
diff --git a/core/store/primitives/src/test/java/org/onosproject/store/primitives/resources/impl/AtomixLeaderElectorTest.java b/core/store/primitives/src/test/java/org/onosproject/store/primitives/resources/impl/AtomixLeaderElectorTest.java
index 1990534..2b1f56b 100644
--- a/core/store/primitives/src/test/java/org/onosproject/store/primitives/resources/impl/AtomixLeaderElectorTest.java
+++ b/core/store/primitives/src/test/java/org/onosproject/store/primitives/resources/impl/AtomixLeaderElectorTest.java
@@ -51,10 +51,10 @@
     public void testRun() throws Throwable {
         leaderElectorRunTests(1);
         clearTests();
-//        leaderElectorRunTests(2);
-//        clearTests();
-//        leaderElectorRunTests(3);
-//        clearTests();
+        leaderElectorRunTests(2);
+        clearTests();
+        leaderElectorRunTests(3);
+        clearTests();
     }
 
     private void leaderElectorRunTests(int numServers) throws Throwable {
@@ -183,6 +183,63 @@
     }
 
     @Test
+    public void testPromote() throws Throwable {
+        leaderElectorPromoteTests(1);
+        clearTests();
+        leaderElectorPromoteTests(2);
+        clearTests();
+        leaderElectorPromoteTests(3);
+        clearTests();
+    }
+
+    private void leaderElectorPromoteTests(int numServers) throws Throwable {
+        createCopycatServers(numServers);
+        Atomix client1 = createAtomixClient();
+        AtomixLeaderElector elector1 = client1.get("test-elector", AtomixLeaderElector.class).join();
+        Atomix client2 = createAtomixClient();
+        AtomixLeaderElector elector2 = client2.get("test-elector", AtomixLeaderElector.class).join();
+        Atomix client3 = createAtomixClient();
+        AtomixLeaderElector elector3 = client3.get("test-elector", AtomixLeaderElector.class).join();
+        elector1.run("foo", node1).join();
+        elector2.run("foo", node2).join();
+
+        LeaderEventListener listener1 = new LeaderEventListener();
+        elector1.addChangeListener(listener1).join();
+        LeaderEventListener listener2 = new LeaderEventListener();
+        elector2.addChangeListener(listener2).join();
+        LeaderEventListener listener3 = new LeaderEventListener();
+        elector3.addChangeListener(listener3).join();
+
+        elector3.promote("foo", node3).thenAccept(result -> {
+            assertFalse(result);
+        }).join();
+
+        assertFalse(listener1.hasEvent());
+        assertFalse(listener2.hasEvent());
+        assertFalse(listener3.hasEvent());
+
+        elector3.run("foo", node3).join();
+
+        listener1.clearEvents();
+        listener2.clearEvents();
+        listener3.clearEvents();
+
+        elector3.promote("foo", node3).thenAccept(result -> {
+            assertTrue(result);
+        }).join();
+
+        listener1.nextEvent().thenAccept(result -> {
+            assertEquals(node3, result.newValue().candidates().get(0));
+        }).join();
+        listener2.nextEvent().thenAccept(result -> {
+            assertEquals(node3, result.newValue().candidates().get(0));
+        }).join();
+        listener3.nextEvent().thenAccept(result -> {
+            assertEquals(node3, result.newValue().candidates().get(0));
+        }).join();
+    }
+
+    @Test
     public void testLeaderSessionClose() throws Throwable {
         leaderElectorLeaderSessionCloseTests(1);
         clearTests();
@@ -325,6 +382,10 @@
             return !eventQueue.isEmpty();
         }
 
+        public void clearEvents() {
+            eventQueue.clear();
+        }
+
         public CompletableFuture<Change<Leadership>> nextEvent() {
             synchronized (this) {
                 if (eventQueue.isEmpty()) {