package org.jgroups.tests;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.jgroups.ChannelException;
import org.jgroups.ExtendedReceiverAdapter;
import org.jgroups.JChannel;
import org.jgroups.util.Promise;
import org.jgroups.util.Util;

/**
 * Tests transfer of large states (http://jira.jboss.com/jira/browse/JGRP-225).
 * Note that on Mac OS, FRAG2.frag_size and max_bundling_size in the transport should be less than 16'000 due to
 * http://jira.jboss.com/jira/browse/JGRP-560. As alternative, increase the MTU of the loopback device to a value
 * greater than max_bundle_size, e.g.
 * ifconfig lo0 mtu 65000
 * @author Bela Ban
 * @version $Id: LargeStateTransferTest.java,v 1.7 2007/09/19 08:43:56 belaban Exp $
 */
public class LargeStateTransferTest extends TestCase {
    JChannel provider, requester;
    Promise p=new Promise();
    String props="udp.xml";
    long start, stop;
    final static int SIZE_1=100000, SIZE_2=1000000, SIZE_3=5000000, SIZE_4=10000000;




    public LargeStateTransferTest(String name) {
        super(name);
    }


    protected void setUp() throws Exception {
        super.setUp();
        props = System.getProperty("props",props);   
        log("Using configuration file " + props);
        provider=new JChannel(props);
        requester=new JChannel(props);
    }

    protected void tearDown() throws Exception {
        if(provider != null)
            provider.close();
        if(requester != null)
            requester.close();
        super.tearDown();
    }


    public void testStateTransfer1() throws ChannelException {
        _testStateTransfer(SIZE_1);
    }

    public void testStateTransfer2() throws ChannelException {
        _testStateTransfer(SIZE_2);
    }

    public void testStateTransfer3() throws ChannelException {
        _testStateTransfer(SIZE_3);
    }

    public void testStateTransfer4() throws ChannelException {
        _testStateTransfer(SIZE_4);
    }



    public void _testStateTransfer(int size) throws ChannelException {
        provider.setReceiver(new Provider(size));
        provider.connect("X");
        p.reset();
        requester.setReceiver(new Requester(p));
        requester.connect("X");
        log("requesting state of " + size + " bytes");
        start=System.currentTimeMillis();
        requester.getState(null, 20000);
        Object result=p.getResult(10000);
        stop=System.currentTimeMillis();
        log("result=" + result + " bytes (in " + (stop-start) + "ms)");
        assertNotNull(result);
        assertEquals(result, new Integer(size));
    }



    static void log(String msg) {
        System.out.println(Thread.currentThread() + " -- "+ msg);
    }

    public static Test suite() {
        return new TestSuite(LargeStateTransferTest.class);
    }

    public static void main(String[] args) {
        junit.textui.TestRunner.run(LargeStateTransferTest.suite());
    }


    private static class Provider extends ExtendedReceiverAdapter {
        byte[] state;

        public Provider(int size) {
            state=new byte[size];
        }

        public byte[] getState() {
            return state;
        }
        
        public void getState(OutputStream ostream){      
            ObjectOutputStream oos =null;
            try{
               oos=new ObjectOutputStream(ostream);
               oos.writeInt(state.length); 
               oos.write(state);
            }
            catch (IOException e){}
            finally{
               Util.close(ostream);
            }
        }
        public void setState(byte[] state) {
            throw new UnsupportedOperationException("not implemented by provider");
        }
    }


    private static class Requester extends ExtendedReceiverAdapter {
        Promise p;

        public Requester(Promise p) {
            this.p=p;
        }

        public byte[] getState() {
            throw new UnsupportedOperationException("not implemented by requester");
        }

        public void setState(byte[] state) {
            p.setResult(new Integer(state.length));
        }
        public void setState(InputStream istream) {
            ObjectInputStream ois=null;
            int size=0;
            try{
               ois= new ObjectInputStream(istream);
               size = ois.readInt();
               byte []stateReceived= new byte[size];
               ois.read(stateReceived);
            }
            catch (IOException e){                        }
            finally{
               Util.close(ois);
            }
            p.setResult(new Integer(size));
        }
    }

}

@@ -209,41 +209,8 @@
 st;%0A
-import junit.framework.TestCase;%0A
 impo
@@ -861,37 +861,35 @@
 v 1.
-7
+8
  2007/
-09/19 08:43:56 belaban
+11/02 13:04:26 vlada
  Exp
@@ -943,13 +943,20 @@
 nds 
+Channel
 Test
-C
+B
 ase 
@@ -1002,16 +1002,25 @@
  Promise
+%3CInteger%3E
  p=new P
@@ -1029,39 +1029,24 @@
 mise
+%3CInteger%3E
 ();
-%0A
     
-String props=%22udp.xml%22;
 %0A   
@@ -1221,32 +1221,102 @@
 er(name);%0A    %7D%0A
+       %0A    public boolean useBlocking() %7B%0A        return true;%0A    %7D%0A
 %0A%0A    protected 
@@ -1369,16 +1369,23 @@
 setUp();
+       
 %0A       
@@ -1385,21 +1385,30 @@
         
-props
+CHANNEL_CONFIG
  = Syste
@@ -1426,73 +1426,44 @@
 ty(%22
-props%22,props);   %0A        log(%22Using configuration file %22 + props
+channel.conf.flush%22, %22flush-udp.xml%22
 );%0A 
@@ -1478,29 +1478,30 @@
 rovider=
-new J
+create
 Channel(
 props);%0A
@@ -1488,29 +1488,27 @@
 eateChannel(
-props
+%22A%22
 );%0A        r
@@ -1520,21 +1520,22 @@
 ter=
-new J
+create
 Channel(
 prop
@@ -1534,13 +1534,11 @@
 nel(
-props
+%22A%22
 );%0A 
@@ -3995,16 +3995,25 @@
  Promise
+%3CInteger%3E
  p;%0A%0A   
@@ -4041,16 +4041,25 @@
 (Promise
+%3CInteger%3E
  p) %7B%0A  

use test framework