package org.apache.catalina.tribes.test.channel;

import junit.framework.TestCase;
import java.io.Serializable;
import java.util.Random;
import java.util.Arrays;
import org.apache.catalina.tribes.ChannelListener;
import org.apache.catalina.tribes.Member;
import org.apache.catalina.tribes.group.GroupChannel;
import java.io.PrintStream;

/**
 * <p>Title: </p> 
 * 
 * <p>Description: </p> 
 * 
 * <p>Copyright: Copyright (c) 2005</p> 
 * 
 * <p>Company: </p>
 * 
 * @author not attributable
 * @version 1.0
 */
public class TestRemoteProcessException extends TestCase {
    int msgCount = 10000;
    GroupChannel channel1;
    GroupChannel channel2;
    Listener listener1;
    protected void setUp() throws Exception {
        super.setUp();
        channel1 = new GroupChannel();
        channel2 = new GroupChannel();
        listener1 = new Listener();
        channel2.addChannelListener(listener1);
        channel1.start(GroupChannel.DEFAULT);
        channel2.start(GroupChannel.DEFAULT);
    }

    protected void tearDown() throws Exception {
        super.tearDown();
        channel1.stop(GroupChannel.DEFAULT);
        channel2.stop(GroupChannel.DEFAULT);
    }

    public void testDataSendSYNCACK() throws Exception {
        System.err.println("Starting SYNC_ACK");
        int errC=0, nerrC=0;
        for (int i=0; i<msgCount; i++) {
            boolean error = Data.r.nextBoolean();
            channel1.send(channel1.getMembers(),Data.createRandomData(error),GroupChannel.SEND_OPTIONS_SYNCHRONIZED_ACK|GroupChannel.SEND_OPTIONS_USE_ACK);
            if ( error ) errC++; else nerrC++;
        }
        System.err.println("Finished SYNC_ACK");
        assertEquals("Checking failure messages.",errC,listener1.errCnt);
        assertEquals("Checking success messages.",nerrC,listener1.noErrCnt);
        assertEquals("Checking all messages.",msgCount,listener1.noErrCnt+listener1.errCnt);
        System.out.println("Listener 1 stats:");
        listener1.printStats(System.out);
    }

    public static class Listener implements ChannelListener {
        long noErrCnt = 0;
        long errCnt = 0;
        public boolean accept(Serializable s, Member m) {
            return (s instanceof Data);
        }

        public void messageReceived(Serializable s, Member m) {
            Data d = (Data)s;
            if ( !Data.verify(d) ) {
                System.err.println("ERROR");
            } else {
                if (d.error) {
                    errCnt++;
                    if ( (errCnt % 100) == 0) {
                        printStats(System.err);
                    }
                    throw new IllegalArgumentException();
                } else {
                    noErrCnt++;
                    if ( (noErrCnt % 100) == 0) {
                        printStats(System.err);
                    }
                }
            }
        }

        public void printStats(PrintStream stream) {
            stream.println("NORMAL:" + noErrCnt);
            stream.println("FAILURES:" + errCnt);
            stream.println("TOTAL:" + (errCnt+noErrCnt));
        }
    }

    public static class Data implements Serializable {
        public int length;
        public byte[] data;
        public byte key;
        public boolean error = false;
        public static Random r = new Random(System.currentTimeMillis());
        public static Data createRandomData(boolean error) {
            int i = r.nextInt();
            i = ( i % 127 );
            int length = Math.abs(r.nextInt() % 65555);
            Data d = new Data();
            d.length = length;
            d.key = (byte)i;
            d.data = new byte[length];
            Arrays.fill(d.data,d.key);
            d.error = error;
            return d;
        }

        public static boolean verify(Data d) {
            boolean result = (d.length == d.data.length);
            for ( int i=0; result && (i<d.data.length); i++ ) result = result && d.data[i] == d.key;
            return result;
        }
    }



}
