/*
 * JBoss, Home of Professional Open Source
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */
package org.jboss.cache.marshall;

import junit.framework.TestCase;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Random;

/**
 * Tests the performance of JBoss Serialization
 *
 * @author <a href="mailto:manik@jboss.org">Manik Surtani (manik@jboss.org)</a>
 */
public class JBossSerializationTest extends TestCase
{
	
	// you can change these variables to change behavior of this testsuite, for debug purposes:
	
	public static boolean SAVE_FILE=false;
	public static boolean USE_STRING=false;
	
	static class DummyObject implements java.io.Serializable 
	{
		private static final long serialVersionUID = -1374365296408936578L;
		String stringName;
		public DummyObject()
		{
			stringName = "Hello world, blah blah blah." + (new Random().nextInt());
		}
		public boolean equals(Object obj)
		{
			return stringName.equals(((DummyObject)obj).stringName);
		}
	}
	
	private static void saveBytes(File fileName,byte[] bytes) throws Exception
	{
		if (SAVE_FILE)
		{
			FileOutputStream fileOut = new FileOutputStream(fileName);
			fileOut.write(bytes);
			fileOut.close();
		}
	}

    public void testSpeedSizeAndDefaults() throws Exception
    {

        assertTrue("JBoss Serialization should be enabled by default", ObjectSerializationFactory.useJBossSerialization);
        Object dummyObject = null;
        
        if (USE_STRING)
        {
        	dummyObject = "Hello world, blah blah blah.";
        }
        else
        {
            dummyObject = new DummyObject();
        }

        ObjectSerializationFactory.useJBossSerialization = false;
        assertTrue("Should be false", !ObjectSerializationFactory.useJBossSerialization);

        
        ByteArrayOutputStream out = new ByteArrayOutputStream();

        long start = 0;
        
        for (int i=0;i<50000;i++)
        {
        	out.reset();
        	if (i==1000)
        	{
        		start=System.currentTimeMillis();
        	}
	        ObjectOutputStream objectOut = ObjectSerializationFactory.createObjectOutputStream(out);
	        objectOut.writeObject( dummyObject );
	        objectOut.close();
	        
	        ObjectInputStream objectInput = ObjectSerializationFactory.createObjectInputStream(out.toByteArray());
	        Object newObject = objectInput.readObject();
	        
	        assertEquals(dummyObject,newObject);
	        assertNotSame(dummyObject,newObject);
        }
        

        long javaSerializationTime = System.currentTimeMillis() - start;
        int javaSerializationSize = out.toByteArray().length;
        
        saveBytes(new File("/tmp/fileJava.bin"),out.toByteArray());
        
        ObjectSerializationFactory.useJBossSerialization = true;
        assertTrue("Should be false", ObjectSerializationFactory.useJBossSerialization);

        start=0;
        for (int i=0;i<50000;i++)
        {
        	out.reset();
        	if (i==1000)
        	{
        		start=System.currentTimeMillis();
        	}
	        ObjectOutputStream objectOut = ObjectSerializationFactory.createObjectOutputStream(out);
	        objectOut.writeObject( dummyObject );
	        objectOut.close();
	        
	        ObjectInputStream objectInput = ObjectSerializationFactory.createObjectInputStream(out.toByteArray());
	        Object newObject = objectInput.readObject();
	        
	        assertEquals(dummyObject,newObject);
	        assertNotSame(dummyObject,newObject);
        }
        long jbossSerializationTime = System.currentTimeMillis() - start;
        int jbossSerializationSize = out.toByteArray().length;
        
        System.out.println("FinishJBoss:" + System.currentTimeMillis());
        saveBytes(new File("/tmp/fileJBoss.bin"),out.toByteArray());
        
        System.out.println("JBossSerialization Time:" + jbossSerializationTime);
        System.out.println("JavaSerialization Time:" + javaSerializationTime);

        System.out.println("JBossSerialization Size:" + jbossSerializationSize);
        System.out.println("JavaSerialization Size:" + javaSerializationSize);

        assertTrue("JBoss Serialization should be FASTER than Java Serialization. Java: " + javaSerializationTime + "; jboss: " + jbossSerializationTime, jbossSerializationTime < javaSerializationTime);
        assertTrue("JBoss Serialization output should be SMALLER than Java Serialization. Java: " + javaSerializationSize + "; jboss: " + jbossSerializationSize, jbossSerializationSize < javaSerializationSize);
    }
    
}
