package org.mitallast.queue.raft;

import org.junit.Before;
import org.mitallast.queue.common.BaseIntegrationTest;
import org.mitallast.queue.common.settings.ImmutableSettings;
import org.mitallast.queue.node.InternalNode;
import org.mitallast.queue.raft.state.RaftStateContext;
import org.mitallast.queue.raft.state.RaftStateType;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Future;

public class BaseRaftTest extends BaseIntegrationTest {

    protected InternalNode[] nodes;
    protected InternalNode leader;

    protected int nodeCount() {
        return 2;
    }

    @Before
    public void setUpNodes() throws Exception {
        int[] ports = new int[nodeCount()];
        nodes = new InternalNode[ports.length];

        StringBuilder buffer = new StringBuilder();
        for (int i = 0; i < ports.length; i++) {
            ports[i] = random.nextInt(10000) + 20000;
            if (i > 0) {
                buffer.append(", ");
            }
            buffer.append("127.0.0.1:").append(ports[i]);
        }
        String nodesString = buffer.toString();

        List<Future<InternalNode>> futures = new ArrayList<>(ports.length);
        for (int i = 0; i < nodes.length; i++) {
            final int node = i;
            Future<InternalNode> future = submit(() -> nodes[node] = createNode(ImmutableSettings.builder()
                .put(settings())
                .put("transport.port", ports[node])
                .put("raft.cluster.nodes", nodesString)
                .build()));
            futures.add(future);
        }

        for (Future<InternalNode> future : futures) {
            future.get();
        }

        // await for leader election
        do {
            Thread.sleep(10);
            for (InternalNode node : nodes) {
                if (node.injector().getInstance(RaftStateContext.class).getState() == RaftStateType.LEADER) {
                    leader = node;
                    break;
                }
            }
        } while (leader == null);
    }
}

@@ -330,36 +330,8 @@
 e;%0A%0A
-import java.util.ArrayList;%0A
 impo
@@ -345,24 +345,24 @@
 .util.List;%0A
+
 import java.
@@ -384,16 +384,125 @@
 .Future;
+%0Aimport java.util.concurrent.TimeUnit;%0Aimport java.util.stream.Collectors;%0Aimport java.util.stream.IntStream;
 %0A%0Apublic
@@ -1205,144 +1205,150 @@
 ture
-%3CInternalNode%3E%3E futures = new ArrayList%3C%3E(ports.length);%0A        for (int i = 0; i %3C nodes.length; i++) %7B%0A            final int
+%3E futures = IntStream.range(0, nodeCount())%0A            .mapToObj(node -%3E submit(() -%3E %7B%0A                logger.info(%22starting
  node 
-= i
+%7B%7D%22, node)
 ;%0A  
@@ -1361,50 +1361,37 @@
     
-Future%3CInternalNode%3E future = submit(() -%3E
+    try %7B%0A                   
  nod
@@ -1440,16 +1440,24 @@
 ilder()%0A
+        
         
@@ -1493,24 +1493,32 @@
             
+        
 .put(%22transp
@@ -1553,24 +1553,32 @@
             
+        
 .put(%22raft.c
@@ -1621,16 +1621,24 @@
         
+        
 .build()
@@ -1638,17 +1638,16 @@
 build())
-)
 ;%0A      
@@ -1656,39 +1656,194 @@
     
-futures.add(future);%0A        %7D%0A
+    %7D catch (Throwable e) %7B%0A                    logger.error(%22error start node%22, e);%0A                    assert false : e;%0A                %7D%0A            %7D)).collect(Collectors.toList());
 %0A   
@@ -1862,22 +1862,8 @@
 ture
-%3CInternalNode%3E
  fut
@@ -1902,16 +1902,35 @@
 ure.get(
+1, TimeUnit.MINUTES
 );%0A     

refactor base raft test