/*
 * Copyright 1999-2011 Alibaba Group.
 *  
 * 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 com.alibaba.dubbo.common.serialize;

import static org.junit.Assert.assertEquals;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;

import org.junit.Test;

import com.alibaba.com.caucho.hessian.io.Hessian2Input;
import com.alibaba.com.caucho.hessian.io.Hessian2Output;
import com.alibaba.dubbo.common.io.Bytes;
import com.alibaba.dubbo.common.serialize.support.dubbo.Builder;
import com.alibaba.dubbo.common.serialize.support.java.CompactedObjectInputStream;
import com.alibaba.dubbo.common.serialize.support.java.CompactedObjectOutputStream;

/**
 * @author qian.lei
 * @author ding.lid
 */
public class SerializationCompareTest
{
	@Test
	public void test_CompareSerializeLength() throws Exception
	{
		long[] data = new long[]{ -1l, 2l, 3l, 4l, 5l };
		ByteArrayOutputStream os;

		os = new ByteArrayOutputStream();
		ObjectOutputStream jos = new ObjectOutputStream(os);
		jos.writeObject(data);
		System.out.println("java:"+Bytes.bytes2hex(os.toByteArray())+":"+os.size());

		os = new ByteArrayOutputStream();
		CompactedObjectOutputStream oos = new CompactedObjectOutputStream(os);
		oos.writeObject(data);
		System.out.println("compacted java:"+Bytes.bytes2hex(os.toByteArray())+":"+os.size());

		os = new ByteArrayOutputStream();
		Hessian2Output h2o = new Hessian2Output(os);
		h2o.writeObject(data);
		h2o.flushBuffer();
		System.out.println("hessian:"+Bytes.bytes2hex(os.toByteArray())+":"+os.size());

		os = new ByteArrayOutputStream();
		Builder<long[]> lb = Builder.register(long[].class);
		lb.writeTo(data, os);
		System.out.println("DataOutput:"+Bytes.bytes2hex(os.toByteArray())+":"+os.size());
	}

	@Test
	public void testBuilderPerm() throws Exception
	{
		Builder<Bean> bb = Builder.register(Bean.class);
		Bean bean = new Bean();
		int len = 0;
		long now = System.currentTimeMillis();
		for(int i=0;i<500;i++)
		{
			ByteArrayOutputStream os = new ByteArrayOutputStream();
			bb.writeTo(bean, os);
			os.close();
			if( i == 0 )
				len = os.toByteArray().length;
			
			ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
			Bean b = bb.parseFrom(is);
			assertEquals(b.getClass(), Bean.class);
		}
		System.out.println("Builder write and parse 500 times in " + (System.currentTimeMillis()-now)+"ms, size " + len);
	}

	@Test
	public void testH2oPerm() throws Exception
	{
		Bean bean = new Bean();
		int len = 0;
		long now = System.currentTimeMillis();
		for(int i=0;i<500;i++)
		{
			ByteArrayOutputStream os = new ByteArrayOutputStream();
			Hessian2Output out = new Hessian2Output(os);
			out.writeObject(bean);
			out.flushBuffer();
			os.close();
			if( i == 0 )
				len = os.toByteArray().length;
			ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
			Hessian2Input in = new Hessian2Input(is);
			assertEquals(in.readObject().getClass(), Bean.class);
		}
		System.out.println("Hessian2 write and parse 500 times in " + (System.currentTimeMillis()-now)+"ms, size " + len);
	}

	@Test
	public void testJavaOutputPerm() throws Exception
	{
		Bean bean = new Bean();
		int len = 0;
		long now = System.currentTimeMillis();
		for(int i=0;i<500;i++)
		{
			ByteArrayOutputStream os = new ByteArrayOutputStream();
			ObjectOutputStream out = new ObjectOutputStream(os);
			out.writeObject(bean);
			os.close();
			if( i == 0 )
				len = os.toByteArray().length;
			ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
			ObjectInputStream in = new ObjectInputStream(is);
			assertEquals(in.readObject().getClass(), Bean.class);
		}
		System.out.println("java write and parse 500 times in " + (System.currentTimeMillis()-now)+"ms, size " + len);
	}

	@Test
	public void testCompactedJavaOutputPerm() throws Exception
	{
		Bean bean = new Bean();
		int len = 0;
		long now = System.currentTimeMillis();
		for(int i=0;i<500;i++)
		{
			ByteArrayOutputStream os = new ByteArrayOutputStream();
			CompactedObjectOutputStream out = new CompactedObjectOutputStream(os);
			out.writeObject(bean);
			os.close();
			if( i == 0 )
				len = os.toByteArray().length;
			ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
			CompactedObjectInputStream in = new CompactedObjectInputStream(is);
			assertEquals(in.readObject().getClass(), Bean.class);
		}
		System.out.println("compacted java write and parse 500 times in " + (System.currentTimeMillis()-now)+"ms, size " + len);
	}

	public static enum EnumTest { READ, WRITE, CREATE, UNREGISTER };

	static class MyList<T> extends ArrayList<T>
	{
        private static final long serialVersionUID = 1L;
        
        private int code = 12345;
		private String id = "feedback";
	}

	static class MyMap<K, V> extends HashMap<K, V>
	{
        private static final long serialVersionUID = 1L;
        
        private int code = 12345;
		private String id = "feedback";
	}

	public static class Bean implements Serializable
	{
		private static final long serialVersionUID = 7737610585231102146L;

		public EnumTest ve = EnumTest.CREATE;

		public int vi = 0;
		public long vl = 100l;

		boolean b = true;
		boolean[] bs = {false, true};

		String s1 = "1234567890";
		String s2 = "1234567890一二三四五六七八九零";

		int i = 123123, ni = -12344, is[] = {1,2,3,4,-1,-2,-3,-4};
		short s = 12, ns = -76;
		double d = 12.345, nd = -12.345;
		long l = 1281447759383l, nl = -13445l;
		private ArrayList<Object> mylist = new ArrayList<Object>();
		{
			mylist.add(1);
			mylist.add("qianlei");
			mylist.add("qianlei");
			mylist.add("qianlei");
			mylist.add("qianlei");
		}
		private HashMap<Object, Object> mymap = new HashMap<Object, Object>();
		{
			mymap.put(1,2);
			mymap.put(2,"1234");
			mymap.put("2345",12938.122);
			mymap.put("2345",-1);
			mymap.put("2345",-1.20);
		}

		public ArrayList<Object> getMylist()
		{
			return mylist;
		}

		public void setMylist(ArrayList<Object> list)
		{
			mylist = list;
		}

		public HashMap<Object, Object> getMymap()
		{
			return mymap;
		}

		public void setMymap(HashMap<Object, Object> map)
		{
			mymap = map;
		}
	}
}