/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.com.caucho.hessian.io;

import com.alibaba.com.caucho.hessian.io.base.SerializeTestBase;
import com.alibaba.com.caucho.hessian.io.beans.Hessian2StringShortType;
import com.alibaba.com.caucho.hessian.io.beans.PersonType;

import org.junit.Test;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertTrue;

public class Hessian1StringShortTest extends SerializeTestBase {

    @Test
    public void serialize_string_short_map_then_deserialize() throws Exception {

        Hessian2StringShortType stringShort = new Hessian2StringShortType();
        Map<String, Short> stringShortMap = new HashMap<String, Short>();
        stringShortMap.put("first", (short)0);
        stringShortMap.put("last", (short)60);
        stringShort.stringShortMap = stringShortMap;

        Hessian2StringShortType deserialize = baseHessianSerialize(stringShort);
        assertTrue(deserialize.stringShortMap != null);
        assertTrue(deserialize.stringShortMap.size() == 2);
        assertTrue(deserialize.stringShortMap.get("last") instanceof Short);
        assertEquals(Short.valueOf((short)0), deserialize.stringShortMap.get("first"));
        assertEquals(Short.valueOf((short)60), deserialize.stringShortMap.get("last"));
    }

    @Test
    public void serialize_string_byte_map_then_deserialize() throws Exception {

        Hessian2StringShortType stringShort = new Hessian2StringShortType();
        Map<String, Byte> stringByteMap = new HashMap<String, Byte>();
        stringByteMap.put("first", (byte)0);
        stringByteMap.put("last", (byte)60);
        stringShort.stringByteMap = stringByteMap;

        Hessian2StringShortType deserialize = baseHessianSerialize(stringShort);
        assertTrue(deserialize.stringByteMap != null);
        assertTrue(deserialize.stringByteMap.size() == 2);
        assertTrue(deserialize.stringByteMap.get("last") instanceof Byte);
        assertEquals(Byte.valueOf((byte)0), deserialize.stringByteMap.get("first"));
        assertEquals(Byte.valueOf((byte) 60), deserialize.stringByteMap.get("last"));
    }

    @Test
    public void serialize_map_then_deserialize() throws Exception {

        Map<String, Short> stringShortMap = new HashMap<String, Short>();
        stringShortMap.put("first", (short)0);
        stringShortMap.put("last", (short)60);

        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        HessianOutput out = new HessianOutput(bout);

        out.writeObject(stringShortMap);
        out.flush();

        ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
        HessianInput input = new HessianInput(bin);
        Map deserialize = (Map) input.readObject(HashMap.class, String.class, Short.class);
        assertTrue(deserialize != null);
        assertTrue(deserialize.size() == 2);
        assertTrue(deserialize.get("last") instanceof Short);
        assertEquals(Short.valueOf((short)0), deserialize.get("first"));
        assertEquals(Short.valueOf((short)60), deserialize.get("last"));
    }

    @Test
    public void serialize_map_then_deserialize0() throws Exception {

        Map<String, Short> stringShortMap = new HashMap<String, Short>();
        stringShortMap.put("first", (short)0);
        stringShortMap.put("last", (short)60);

        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        HessianOutput out = new HessianOutput(bout);

        out.writeObject(stringShortMap);
        out.flush();

        ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
        HessianInput input = new HessianInput(bin);
        List<Class<?>> keyValueType = new ArrayList<Class<?>>();
        keyValueType.add(String.class);
        keyValueType.add(short.class);

        Map deserialize = (Map) input.readObject(keyValueType);
        assertTrue(deserialize != null);
        assertTrue(deserialize.size() == 2);
        assertTrue(deserialize.get("last") instanceof Short);
        assertEquals(Short.valueOf((short)0), deserialize.get("first"));
        assertEquals(Short.valueOf((short)60), deserialize.get("last"));
    }

    @Test
    public void serialize_string_person_map_then_deserialize() throws Exception {

        Hessian2StringShortType stringShort = new Hessian2StringShortType();
        Map<String, PersonType> stringPersonTypeMap = new HashMap<String, PersonType>();
        stringPersonTypeMap.put("first", new PersonType(
                "jason.shang", 26, (double) 0.1, (short)1, (byte)2, Arrays.asList((short)1,(short)1)
        ));
        stringPersonTypeMap.put("last", new PersonType(
                "jason.shang2", 52, (double) 0.2, (short)2, (byte)4, Arrays.asList((short)2,(short)2)
        ));
        stringShort.stringPersonTypeMap = stringPersonTypeMap;

        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        HessianOutput out = new HessianOutput(bout);

        out.writeObject(stringShort);
        out.flush();

        ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
        HessianInput input = new HessianInput(bin);

        Hessian2StringShortType deserialize = (Hessian2StringShortType) input.readObject();
        assertTrue(deserialize.stringPersonTypeMap != null);
        assertTrue(deserialize.stringPersonTypeMap.size() == 2);
        assertTrue(deserialize.stringPersonTypeMap.get("last") instanceof PersonType);


        assertEquals(new PersonType(
                "jason.shang", 26, (double) 0.1, (short)1, (byte)2, Arrays.asList((short)1,(short)1)
        ), deserialize.stringPersonTypeMap.get("first"));

        assertEquals(new PersonType(
                "jason.shang2", 52, (double) 0.2, (short)2, (byte)4, Arrays.asList((short)2,(short)2)
        ), deserialize.stringPersonTypeMap.get("last"));

    }

    @Test
    public void serialize_list_then_deserialize() throws Exception {

        List<Short> shortList = new ArrayList<Short>();
        shortList.add((short)0);
        shortList.add((short)60);

        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        HessianOutput out = new HessianOutput(bout);

        out.writeObject(shortList);
        out.flush();

        ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
        HessianInput input = new HessianInput(bin);
        List<Short> deserialize = (List) input.readObject(ArrayList.class, Short.class);
        assertTrue(deserialize != null);
        assertTrue(deserialize.size() == 2);
        assertTrue(deserialize.get(1) instanceof Short);
        assertEquals(Short.valueOf((short)0), deserialize.get(0));
        assertEquals(Short.valueOf((short)60), deserialize.get(1));
    }

    @Test
    public void serialize_list_then_deserialize0() throws Exception {

        List<Short> shortList = new ArrayList<Short>();
        shortList.add((short)0);
        shortList.add((short)60);

        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        HessianOutput out = new HessianOutput(bout);

        out.writeObject(shortList);
        out.flush();

        ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
        HessianInput input = new HessianInput(bin);

        List<Class<?>> valueType = new ArrayList<Class<?>>();
        valueType.add(short.class);

        List<Short> deserialize = (List) input.readObject(valueType);
        assertTrue(deserialize != null);
        assertTrue(deserialize.size() == 2);
        assertTrue(deserialize.get(1) instanceof Short);
        assertEquals(Short.valueOf((short)0), deserialize.get(0));
        assertEquals(Short.valueOf((short)60), deserialize.get(1));
    }

}
