package com.yahoo.omid.tsoclient;

import static com.google.common.collect.Sets.newHashSet;
import static com.yahoo.omid.tsoclient.TSOClient.TSO_HOST_CONFKEY;
import static com.yahoo.omid.tsoclient.TSOClient.TSO_PORT_CONFKEY;
import static org.slf4j.LoggerFactory.getLogger;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

import org.apache.commons.configuration.BaseConfiguration;
import org.apache.commons.configuration.Configuration;
import org.slf4j.Logger;
import org.testng.annotations.Test;

import com.yahoo.omid.tso.util.DummyCellIdImpl;
import com.yahoo.omid.tsoclient.TSOClient.ConnectionException;
import com.yahoo.omid.tsoclient.TSOClientImpl.BaseState;
import com.yahoo.omid.tsoclient.TSOClientImpl.ConnectionFailedState;
import com.yahoo.omid.tsoclient.TSOClientImpl.DisconnectedState;
import com.yahoo.statemachine.StateMachine.FsmImpl;

/**
 * Test the behavior of requests on a TSOClient component that is not
 * connected to a TSO server.
 */
public class TestUnconnectedTSOClient {

    private static final Logger LOG = getLogger(TestUnconnectedTSOClient.class);


    @Test(timeOut = 30_000) // 30 secs
    public void testRequestsDoneOnAnUnconnectedTSOClientAlwaysReturn()
    throws Exception {

        Configuration clientConf = new BaseConfiguration();
        clientConf.setProperty(TSO_HOST_CONFKEY, "localhost");
        clientConf.setProperty(TSO_PORT_CONFKEY, 12345);

        // Component under test
        TSOClient tsoClient = TSOClient.newBuilder()
                                       .withConfiguration(clientConf)
                                       .build();

        // Internal accessor to fsm
        TSOClientImpl clientimpl = (TSOClientImpl)tsoClient;
        FsmImpl fsm = (FsmImpl) clientimpl.fsm;

        assertEquals(fsm.getState().getClass(), DisconnectedState.class);

        // Test requests to the 3 relevant methods in TSO client

        List<Class<? extends BaseState>> EXPECTED_EXCEPTIONS =
                Arrays.asList(DisconnectedState.class, ConnectionFailedState.class);
        try {
            tsoClient.getNewStartTimestamp().get();
            fail();
        } catch (ExecutionException e) {
            LOG.info("Exception expected");
            assertEquals(e.getCause().getClass(), ConnectionException.class);
            assertTrue(EXPECTED_EXCEPTIONS.contains(fsm.getState().getClass()));
        }

        try {
            tsoClient.commit(1, newHashSet(new DummyCellIdImpl(0xdeadbeefL))).get();
            fail();
        } catch (ExecutionException e) {
            LOG.info("Exception expected");
            assertEquals(e.getCause().getClass(), ConnectionException.class);
            assertTrue(EXPECTED_EXCEPTIONS.contains(fsm.getState().getClass()));
        }

        TimeUnit.SECONDS.sleep(TSOClient.DEFAULT_TSO_RECONNECTION_DELAY_SECS);
        assertEquals(fsm.getState().getClass(), DisconnectedState.class);

        tsoClient.close().get();
        LOG.info("No exception expected");

    }

}

@@ -85,16 +85,94 @@
 ashSet;%0A
+import static com.yahoo.omid.tsoclient.TSOClient.TSO_RECONNECTION_DELAY_SECS;%0A
 import s
@@ -428,106 +428,14 @@
 ert.
-assertTrue;%0Aimport static org.testng.Assert.fail;%0A%0Aimport java.util.Arrays;%0Aimport java.util.List;
+fail;%0A
 %0Aimp
@@ -809,134 +809,8 @@
 on;%0A
-import com.yahoo.omid.tsoclient.TSOClientImpl.BaseState;%0Aimport com.yahoo.omid.tsoclient.TSOClientImpl.ConnectionFailedState;%0A
 impo
@@ -1154,16 +1154,90 @@
 lass);%0A%0A
+    private static final int TSO_RECONNECTION_DELAY_IN_SECS_FOR_TEST = 2;%0A
 %0A    @Te
@@ -1542,16 +1542,118 @@
  12345);
+%0A        clientConf.setProperty(TSO_RECONNECTION_DELAY_SECS, TSO_RECONNECTION_DELAY_IN_SECS_FOR_TEST);
 %0A%0A      
@@ -2142,156 +2142,8 @@
 nt%0A%0A
-        List%3CClass%3C? extends BaseState%3E%3E EXPECTED_EXCEPTIONS =%0A                Arrays.asList(DisconnectedState.class, ConnectionFailedState.class);%0A
     
@@ -2403,46 +2403,100 @@
     
-assertTrue(EXPECTED_EXCEPTIONS.contain
+TimeUnit.SECONDS.sleep(TSO_RECONNECTION_DELAY_IN_SECS_FOR_TEST * 2);%0A            assertEqual
 s(fs
@@ -2510,33 +2510,57 @@
 ate().getClass()
-)
+, DisconnectedState.class
 );%0A        %7D%0A%0A  
@@ -2847,96 +2847,8 @@
     
-        assertTrue(EXPECTED_EXCEPTIONS.contains(fsm.getState().getClass()));%0A        %7D%0A%0A
     
@@ -2878,26 +2878,8 @@
 eep(
-TSOClient.DEFAULT_
 TSO_
@@ -2901,15 +2901,35 @@
 LAY_
+IN_
 SECS
-);%0A
+_FOR_TEST * 2);%0A    
     
@@ -2989,32 +2989,42 @@
 tedState.class);
+%0A        %7D
 %0A%0A        tsoCli
@@ -3085,17 +3085,16 @@
 cted%22);%0A
-%0A
     %7D%0A%0A%7D

Fix tests for unconnected TSO clients