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.List;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

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> futures = IntStream.range(0, nodeCount())
            .mapToObj(node -> submit(() -> {
                logger.info("starting node {}", node);
                try {
                    nodes[node] = createNode(ImmutableSettings.builder()
                        .put(settings())
                        .put("transport.port", ports[node])
                        .put("raft.cluster.nodes", nodesString)
                        .build());
                } catch (Throwable e) {
                    logger.error("error start node", e);
                    assert false : e;
                }
            })).collect(Collectors.toList());
        for (Future future : futures) {
            future.get(1, TimeUnit.MINUTES);
        }

        // 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);
    }
}

@@ -423,16 +423,62 @@
 meUnit;%0A
+import java.util.concurrent.TimeoutException;%0A
 import j
@@ -717,17 +717,17 @@
  return 
-2
+3
 ;%0A    %7D%0A
@@ -1776,17 +1776,26 @@
 art node
-%22
+ %7B%7D%22, node
 , e);%0A  
@@ -1830,16 +1830,108 @@
 se : e;%0A
+                %7D finally %7B%0A                    logger.info(%22starting node %7B%7D done%22, node);%0A
         
@@ -2022,24 +2022,46 @@
  futures) %7B%0A
+            try %7B%0A    
             
@@ -2093,16 +2093,98 @@
 NUTES);%0A
+            %7D catch (TimeoutException e) %7B%0A                throw e;%0A            %7D%0A
         

refactor base raft test