#!/usr/bin/env python3
# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# 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.

import asyncio
import pickle
import unittest
from typing import Mapping, Union, Hashable

from testing.types import (
    Digits,
    I32List,
    Integers,
    SetI32,
    StringBucket,
    StrStrMap,
    easy,
    hard,
)
from thrift.py3.common import Protocol
from thrift.py3.exceptions import Error
from thrift.py3.serializer import (
    Transform,
    deserialize,
    deserialize_from_header,
    deserialize_with_length,
    serialize,
    serialize_iobuf,
    serialize_with_header,
    serialize_with_header_iobuf,
)
from thrift.py3.types import Struct


class SerializerTests(unittest.TestCase):
    def test_with_header_bytes(self) -> None:
        control = easy(val=5, val_list=[4, 3, 2, 1])
        buf = serialize_with_header(control, transform=Transform.ZSTD_TRANSFORM)
        decoded = deserialize_from_header(easy, buf)
        self.assertEqual(control, decoded)

    def test_with_header_iobuf(self) -> None:
        control = easy(val=5, val_list=[4, 3, 2, 1])
        iobuf = serialize_with_header_iobuf(control, transform=Transform.ZSTD_TRANSFORM)
        decoded = deserialize_from_header(easy, iobuf)
        self.assertEqual(control, decoded)

    def test_with_header_iobuf_binary(self) -> None:
        control = easy(val=6, val_list=[5, 4, 3, 2, 1])
        iobuf = serialize_with_header_iobuf(
            control, protocol=Protocol.BINARY, transform=Transform.ZLIB_TRANSFORM
        )
        decoded = deserialize_from_header(easy, iobuf)
        self.assertEqual(control, decoded)

    def test_with_header_iobuf_json(self) -> None:
        control = easy(val=4, val_list=[3, 2, 1])
        iobuf = serialize_with_header_iobuf(control, protocol=Protocol.JSON)
        decoded = deserialize_from_header(easy, iobuf)
        self.assertEqual(control, decoded)

    def test_None(self) -> None:
        with self.assertRaises(TypeError):
            # pyre-fixme[6]: Expected `sT` for 1st param but got `None`.
            serialize(None, Protocol.JSON)

    def test_sanity(self) -> None:
        with self.assertRaises(TypeError):
            # pyre-fixme[6]: Expected `sT` for 1st param but got `int`.
            serialize(1, Protocol.COMPACT)

        with self.assertRaises(TypeError):
            # pyre-fixme[6]: Expected `Protocol` for 2nd param but got `None`.
            serialize(easy(), None)

        with self.assertRaises(TypeError):