/*
 * 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.Assert;
import org.junit.Test;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.*;

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

public class Hessian2StringShortTest 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 = baseHessian2Serialize(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 = baseHessian2Serialize(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();
        Hessian2Output out = new Hessian2Output(bout);

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

        ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
        Hessian2Input input = new Hessian2Input(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();
        Hessian2Output out = new Hessian2Output(bout);

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

        ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
        Hessian2Input input = new Hessian2Input(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();
        Hessian2Output out = new Hessian2Output(bout);

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

        ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
        Hessian2Input input = new Hessian2Input(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();
        Hessian2Output out = new Hessian2Output(bout);

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

        ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
        Hessian2Input input = new Hessian2Input(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();
        Hessian2Output out = new Hessian2Output(bout);

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

        ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
        Hessian2Input input = new Hessian2Input(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));
    }

    @Test
    public void serialize_short_set_then_deserialize() throws Exception {

        Hessian2StringShortType stringShort = new Hessian2StringShortType();
        Set<Short> shortSet = new HashSet<Short>();
        shortSet.add((short) 0);
        shortSet.add((short) 60);
        stringShort.shortSet = shortSet;

        Hessian2StringShortType deserialize = baseHessian2Serialize(stringShort);
        assertTrue(deserialize.shortSet != null);
        assertTrue(deserialize.shortSet.size() == 2);
        assertTrue(deserialize.shortSet.contains((short) 0));
        assertTrue(deserialize.shortSet.contains((short) 60));
    }

    @Test
    public void test_string_short_type() throws IOException {
        for (int i = 0; i < 100; i++) {
            Hessian2StringShortType obj = new Hessian2StringShortType();
            obj.shortSet = new HashSet<>();
            obj.stringShortMap = new HashMap<>();
            obj.stringByteMap = new HashMap<>();
            obj.stringPersonTypeMap = new HashMap<>();

            obj.shortSet.add((short) i);
            obj.shortSet.add((short) (i * 2));

            obj.stringShortMap.put(String.valueOf(i), (short) i);
            obj.stringShortMap.put(String.valueOf(i * 100), (short) (i * 100));
            obj.stringByteMap.put(String.valueOf(i), (byte) 1);

            List<Short> shorts = Arrays.asList((short) 12, (short) 4);
            PersonType abc = new PersonType("ABC", 12, 128D, (short) 1, (byte) 2, shorts);
            obj.stringPersonTypeMap.put("P_" + i, abc);

            Hessian2StringShortType newObj = baseHessian2Serialize(obj);
            Assert.assertEquals(obj, newObj);
            System.out.println("ShortTypeTest.testHessian2StringShortType(): i=" + i + " passed!");
        }
    }
}
