/*
 * Copyright 1999,2005 The Apache Software Foundation.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.apache.catalina.cluster.tcp;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;

import junit.framework.TestCase;

/**
 * @author Peter Rossbach
 * 
 * @version $Revision$ $Date$
 */
public class DataSenderTest extends TestCase {
    
    /**
     * Test that close Socket before socket open again!
     * @throws Exception
     */
    public void testOpenAgain() throws Exception {
        DataSender sender = createMockDataSender(); 
        assertEquals(1,sender.getSocketOpenCounter());
        assertEquals(0,sender.getSocketCloseCounter());
        sender.openSocket() ;
        assertEquals(1,sender.getSocketOpenCounter());
        assertEquals(0,sender.getSocketCloseCounter());
        sender.closeSocket() ;
        sender.openSocket() ;
        assertEquals(1,sender.getSocketCloseCounter());
        assertEquals(2,sender.getSocketOpenCounter());
    }
    
    /**
     * Test Connect/disconnet open and close underlying sockets
     * @throws Exception
     */
    public void testConnectDisconnect() throws Exception {
        InetAddress host = InetAddress.getByName("127.0.0.1");
        DataSender sender = new MockDataSender("catalina",host, 3434);
        sender.connect() ;
        assertTrue(sender.isConnected());
        assertEquals(1,sender.getSocketOpenCounter());
        assertEquals(0,sender.getSocketCloseCounter());
        assertEquals(1,sender.getConnectCounter());
        sender.disconnect();
        assertFalse(sender.isConnected());
        assertEquals(1,sender.getSocketCloseCounter());
        assertEquals(1,sender.getDisconnectCounter());
   }
    
    /**
     * Test Socket setup and OpenClose Counter
     * @throws Exception
     */
    public void testOpenCloseSocketCounter() throws Exception {
        DataSender sender = createMockDataSender();
        assertEquals(0, sender.getSocket().getSoTimeout());
        sender.closeSocket();
        assertEquals(1, sender.getSocketOpenCounter());
        assertEquals(1, sender.getSocketCloseCounter());
    }

    /**
     * Test Socket IOException with SocketCounter increment
     * @throws Exception
     */
    public void testFailedOpenSocketCounter() throws Exception {
        InetAddress host = InetAddress.getByName("127.0.0.1");
        DataSender sender = new MockFailedDataSender("catalina",host, 3434);
        try {
            sender.openSocket();
            fail("Sender not send expected IOException");
        } catch (IOException ioe) {
            assertEquals(0, sender.getSocketOpenCounter());
            assertEquals(1, sender.getSocketOpenFailureCounter());
        }
    }

    /**
     * read ack from receiver
     * @throws Exception
     */
    public void testWaitForAck() throws Exception {
        DataSender sender = createMockDataSender();
        assertNotNull(sender.getSocket());
        sender.waitForAck(15000);  
        ByteArrayInputStream stream = (ByteArrayInputStream)sender.getSocket().getInputStream();
        assertEquals(-1,stream.read());
    }
    
    /**
     * @return
     * @throws UnknownHostException
     * @throws IOException
     * @throws SocketException
     */
    private DataSender createMockDataSender() throws UnknownHostException, IOException, SocketException {
        InetAddress host = InetAddress.getByName("127.0.0.1");
        DataSender sender = new MockDataSender("catalina",host, 3434);
        sender.openSocket();
        return sender;
    }

    /**
     * Send message with  wait ack and simulate ack Exceptions
     * @throws Exception
     */
    public void testWriteData()throws Exception {
        DataSender sender = createMockDataSender();
        ClusterData data = new ClusterData("test", "123",new byte[]{ 1,2,3 }, System.currentTimeMillis() );
        sender.writeData(data) ;
        ByteArrayOutputStream stream = (ByteArrayOutputStream)sender.getSocket().getOutputStream();
        assertEquals(25,stream.size());
        ByteArrayInputStream istream = (ByteArrayInputStream)sender.getSocket().getInputStream();
        assertEquals(6,istream.read());    
        MockSocket socket =((MockSocket)sender.getSocket());
        socket.reset();
        sender.setWaitForAck(true);
        socket.setReadIOException(true);
        try {
            sender.writeData(data);
            fail("Missing Ack IOException") ;
        } catch (IOException ioe) {} ;
        socket.reset();
        socket.setReadIOException(false);
        socket.setReadSocketTimeoutException(true);
        try {
            sender.writeData(data);
            fail("Missing Ack SocketTimeoutException") ;
        } catch (SocketTimeoutException soe) {} ;               

    }
    
    /**
     * Send message without wait ack
     * @throws Exception
     */
    public void testWriteDataWithOutAck()throws Exception {
        InetAddress host = InetAddress.getByName("127.0.0.1");
        DataSender sender = new MockDataSender("catalina",host, 3434);
        sender.setWaitForAck(false);
        sender.openSocket();
        ClusterData data = new ClusterData("test", "123",new byte[]{ 1,2,3 }, System.currentTimeMillis() );
        sender.writeData(data) ;
        ByteArrayOutputStream stream = (ByteArrayOutputStream)sender.getSocket().getOutputStream();
        assertEquals(25,stream.size());
        ByteArrayInputStream istream = (ByteArrayInputStream)sender.getSocket().getInputStream();
        assertEquals(3,TcpReplicationThread.ACK_COMMAND.length);
        assertEquals(TcpReplicationThread.ACK_COMMAND[0],istream.read());        
        assertEquals(TcpReplicationThread.ACK_COMMAND[1],istream.read());        
        assertEquals(TcpReplicationThread.ACK_COMMAND[2],istream.read());   
     }
    
    /**
     * Check close socket fro keep alive handling is correct (number of request and timeout
     * @throws Exception
     */
    public void testCheckKeepAlive() throws Exception {
        DataSender sender = createMockDataSender() ;
        assertFalse(sender.checkKeepAlive()) ;
        sender.setKeepAliveMaxRequestCount(1);
        sender.keepAliveCount = 1;
        assertTrue(sender.checkKeepAlive());
        assertEquals(1,sender.getSocketCloseCounter());
        assertEquals(0,sender.getKeepAliveCount());
        sender.openSocket();
        assertEquals(0,sender.getKeepAliveCount());
        sender.setKeepAliveMaxRequestCount(100);
        sender.keepAliveConnectTime = System.currentTimeMillis() - sender.getKeepAliveTimeout() ;
        assertFalse(sender.checkKeepAlive());
        assertTrue(sender.isConnected());
        assertEquals(1,sender.getSocketCloseCounter());
        sender.keepAliveConnectTime-- ;
        assertTrue(sender.checkKeepAlive());
        assertEquals(2,sender.getSocketCloseCounter());
    }
    
    
    /**
     * Push a mesage over moch socket to receiver
     * @throws Exception
     */
    public void testPushMessage() throws Exception {
        InetAddress host = InetAddress.getByName("127.0.0.1");
        DataSender sender = new MockDataSender("catalina",host, 3434);
        assertFalse(sender.isConnected());
        assertPushMessage(sender);
        ((MockSocket)sender.getSocket()).reset();
        // let see the processingtime 
        sender.setDoProcessingStats(true);
        pushMessage(sender);
        assertEquals(sender.getProcessingTime(),sender.getMinProcessingTime());
        assertEquals(sender.getProcessingTime(),sender.getMaxProcessingTime());
    }
   
    /**
     * Test retry after socket write failure
     * @throws Exception
     */
    public void testPushMessageRetryFailure() throws Exception {
        InetAddress host = InetAddress.getByName("127.0.0.1");
        DataSender sender = new MockDataSender("catalina",host, 3434);
        sender.setResend(true);
        sender.openSocket() ;
        ((MockSocket)sender.getSocket()).setWriteIOException(true);
        assertPushMessage(sender);
        assertEquals(2,sender.getSocketOpenCounter());
        assertEquals(1,sender.getSocketCloseCounter());
    }
    
    /**
     * Test socket closed after socket write failure without retry
     * @throws Exception
     */
    public void testPushMessageFailure() throws Exception {
        InetAddress host = InetAddress.getByName("127.0.0.1");
        DataSender sender = new MockDataSender("catalina",host, 3434);
        sender.openSocket() ;
        ((MockSocket)sender.getSocket()).setWriteIOException(true);
        try {
            assertPushMessage(sender);
            fail("No IOException is thrown");
        } catch (IOException ioe) {}
        assertFalse(sender.isConnected());
        assertEquals(1,sender.getSocketOpenCounter());
        assertEquals(1,sender.getSocketCloseCounter());
    }

    /**
     * @param sender
     * @throws IOException
     */
    private void assertPushMessage(DataSender sender) throws IOException {
        ByteArrayOutputStream stream = pushMessage(sender);
        assertEquals("message format is wrong",25,stream.size());
        assertEquals("socket is not at keep alive mode",1,sender.getKeepAliveCount());
        assertEquals("no stats or wrong number of request message counter",1,sender.getNrOfRequests());
        assertEquals("to long operation",0,sender.getProcessingTime());
        assertEquals(Long.MAX_VALUE,sender.getMinProcessingTime());
    }

    /**
     * @param sender
     * @return
     * @throws IOException
     */
    private ByteArrayOutputStream pushMessage(DataSender sender) throws IOException {
        ClusterData data = new ClusterData("unique-id", "123",new byte[]{ 1,2,3 }, System.currentTimeMillis() );
        sender.pushMessage(data );
        assertTrue("sender is not connect after message pushed!",sender.isConnected());
        ByteArrayOutputStream stream = (ByteArrayOutputStream)sender.getSocket().getOutputStream();
        return stream;
    }

    /**
     * Simulate Create socket failure 
     */
    class MockFailedDataSender extends DataSender {

        /**
         * @param host
         * @param port
         */
        public MockFailedDataSender(String domain,InetAddress host, int port) {
            super(domain,host, port);
        }

        /*
         * throw IOException
         * 
         * @see org.apache.catalina.cluster.tcp.DataSender#createSocket()
         */
        protected void createSocket() throws IOException, SocketException {
            throw new IOException();
        }
    }

    /**
     * Simulate open real socket to a server!!
     */
    class MockDataSender extends DataSender {

        
        /**
         * @param host
         * @param port
         */
        public MockDataSender(String domain,InetAddress host, int port) {
            super(domain,host, port);
            
        }

        protected void createSocket() throws IOException, SocketException {
            setSocket(new MockSocket(getAddress(), getPort()));
        }
        
    }
    
    /**
     * Don't open Socket really
     */
    class MockSocket extends Socket {

        private InputStream ackInputStream ;
        private OutputStream messageStream ;
        private boolean writeIOException = false ;
        private boolean readIOException = false ;
        private boolean readSocketTimeoutException = false ;
               
        /**
         * @param address
         * @param port
         * @throws java.io.IOException
         */
        public MockSocket(InetAddress address, int port) throws IOException {
            ackInputStream = new ByteArrayInputStream(TcpReplicationThread.ACK_COMMAND);
            messageStream = new ByteArrayOutputStream() ;
        }
        
        public void reset() throws IOException {
           ackInputStream.reset() ;
        }
        
        
        /**
         * @return Returns the readIOException.
         */
        public boolean isReadIOException() {
            return readIOException;
        }
        
        /**
         * @param readIOException The readIOException to set.
         */
        public void setReadIOException(boolean readIOException) {
            this.readIOException = readIOException;
        }
        
        /**
         * @return Returns the readSocketTimeoutException.
         */
        public boolean isReadSocketTimeoutException() {
            return readSocketTimeoutException;
        }
        
        /**
         * @param readSocketTimeoutException The readSocketTimeoutException to set.
         */
        public void setReadSocketTimeoutException(
                boolean readSocketTimeoutException) {
            this.readSocketTimeoutException = readSocketTimeoutException;
        }
        /**
         * @return Returns the writeIOException.
         */
        public boolean isWriteIOException() {
            return writeIOException;
        }
        
        /**
         * @param writeIOException The writeIOException to set.
         */
        public void setWriteIOException(boolean writeIOException) {
            this.writeIOException = writeIOException;
        }
        
        /**
         *  get ack Stream ( 3 bytes)
         * @see TcpReplicationThread#ACK_COMMAND
         * @see java.net.Socket#getInputStream()
         */
        public InputStream getInputStream() throws IOException {
            if(isReadIOException()) {
                throw new IOException("MockSocket");
            }
            if(isReadSocketTimeoutException()) {
                throw new SocketTimeoutException("MockSocket");
            }
            return ackInputStream;
        }
        
        
        /**
         * Buffer Output in simple byte array stream
         * @see java.net.Socket#getOutputStream()
         */
        public OutputStream getOutputStream() throws IOException {
            if(isWriteIOException()) {
                throw new IOException("MockSocket");
            }
            return messageStream;
        }
    }
}
