# Copyright (c) Facebook, Inc. and its affiliates # SPDX-License-Identifier: MIT OR Apache-2.0 from collections import OrderedDict from dataclasses import dataclass import unittest import serde_types as st import bincode import typing class BincodeTestCase(unittest.TestCase): def test_bincode_bool(self): self.assertEqual(bincode.serialize(False, bool), b"\x00") self.assertEqual(bincode.serialize(True, bool), b"\x01") self.assertEqual(bincode.deserialize(b"\x00", bool), (False, b"")) self.assertEqual(bincode.deserialize(b"\x01", bool), (True, b"")) with self.assertRaises(st.DeserializationError): bincode.deserialize(b"\x02", bool) with self.assertRaises(st.DeserializationError): bincode.deserialize(b"", bool) def test_bincode_u8(self): self.assertEqual(bincode.serialize(0x1, st.uint8), b"\x01") self.assertEqual(bincode.deserialize(b"\xff", st.uint8), (255, b"")) def test_bincode_u16(self): self.assertEqual(bincode.serialize(0x0102, st.uint16), b"\x02\x01") self.assertEqual(bincode.deserialize(b"\xff\xff", st.uint16), (65535, b"")) def test_bincode_u32(self): self.assertEqual(bincode.serialize(0x01020304, st.uint32), b"\x04\x03\x02\x01") self.assertEqual( bincode.deserialize(b"\xff\xff\xff\xff", st.uint32), (4294967295, b"") ) def test_bincode_u64(self): self.assertEqual( bincode.serialize(0x0102030405060708, st.uint64), b"\x08\x07\x06\x05\x04\x03\x02\x01", ) self.assertEqual( bincode.deserialize(b"\xff" * 8, st.uint64), ((1 << 64) - 1, b"") ) def test_bincode_u128(self): self.assertEqual( bincode.serialize( st.uint128(0x0102030405060708090A0B0C0D0E0F10), st.uint128 ), b"\x10\x0f\x0e\r\x0c\x0b\n\t\x08\x07\x06\x05\x04\x03\x02\x01", ) self.assertEqual( bincode.deserialize(b"\xff" * 16, st.uint128), (st.uint128((1 << 128) - 1), b""), ) def test_bincode_i8(self): self.assertEqual(bincode.serialize(4, st.int8), b"\x04") self.assertEqual(bincode.serialize(-2, st.int8), b"\xfe") self.assertEqual(bincode.deserialize(b"\xff", st.int8), (-1, b"")) def test_bincode_i16(self): self.assertEqual(bincode.serialize(0x0102, st.int16), b"\x02\x01") self.assertEqual(bincode.deserialize(b"\xff\xff", st.int16), (-1, b"")) def test_bincode_i32(self): self.assertEqual(bincode.serialize(0x01020304, st.int32), b"\x04\x03\x02\x01") self.assertEqual(bincode.deserialize(b"\xff\xff\xff\xff", st.int32), (-1, b"")) def test_bincode_i64(self): self.assertEqual( bincode.serialize(0x0102030405060708, st.int64), b"\x08\x07\x06\x05\x04\x03\x02\x01", ) self.assertEqual(bincode.deserialize(b"\xff" * 8, st.int64), (-1, b"")) def test_bincode_i128(self): self.assertEqual( bincode.serialize(st.int128(0x0102030405060708090A0B0C0D0E0F10), st.int128), b"\x10\x0f\x0e\r\x0c\x0b\n\t\x08\x07\x06\x05\x04\x03\x02\x01", ) self.assertEqual( bincode.deserialize(b"\xff" * 16, st.int128), (st.int128(-1), b"") ) def test_bincode_f32(self): self.assertEqual(bincode.serialize(0.3, st.float32), b"\x9a\x99\x99\x3e") value, reminder = bincode.deserialize(b"\x9a\x99\x99\x3e", st.float32) self.assertEqual(reminder, b"") self.assertAlmostEqual(value, 0.3) def test_bincode_f64(self): self.assertEqual( bincode.serialize(0.000000000003, st.float64), b"\x1a\xdf\xc4\x41\x66\x63\x8a\x3d", ) value, reminder = bincode.deserialize( b"\x1a\xdf\xc4\x41\x66\x63\x8a\x3d", st.float64 ) self.assertEqual(reminder, b"") self.assertAlmostEqual(value, 0.000000000003) def test_serialize_bytes(self): self.assertEqual(bincode.serialize(b"", bytes), b"\x00" * 8) self.assertEqual( bincode.serialize(b"\x00\x00", bytes), b"\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00", ) self.assertEqual( bincode.serialize(b"\x00" * 128, bytes), b"\x80\x00\x00\x00\x00\x00\x00\x00" + b"\x00" * 128, ) self.assertEqual(bincode.deserialize(b"\x00" * 8, bytes), (b"", b"")) def test_serialize_tuple(self): T = typing.Tuple[st.uint8, st.uint16] self.assertEqual(bincode.serialize((0, 1), T), b"\x00\x01\x00") self.assertEqual(bincode.deserialize(b"\x02\x01\x00", T), ((2, 1), b"")) def test_serialize_option(self): T = typing.Optional[st.uint16] self.assertEqual(bincode.serialize(None, T), b"\x00") self.assertEqual(bincode.serialize(6, T), b"\x01\x06\x00") self.assertEqual(bincode.deserialize(b"\x00", T), (None, b"")) self.assertEqual(bincode.deserialize(b"\x01\x02\x00", T), (2, b"")) with self.assertRaisesRegex(st.DeserializationError, "Wrong tag.*"): bincode.deserialize(b"\x02\x06\x00", T) def test_serialize_sequence(self): Seq = typing.Sequence[st.uint16] self.assertEqual( bincode.serialize([], Seq), b"\x00\x00\x00\x00\x00\x00\x00\x00" ) self.assertEqual( bincode.serialize([0, 1], Seq), b"\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00", ) self.assertEqual( bincode.serialize([256] * 256, Seq), b"\x00\x01\x00\x00\x00\x00\x00\x00" + b"\x00\x01" * 256, ) self.assertEqual( bincode.deserialize(b"\x01\x00\x00\x00\x00\x00\x00\x00\x03\x00", Seq), ([3], b""), ) def test_serialize_str(self): self.assertEqual( bincode.serialize("ABC\u0394", str), b"\x05\x00\x00\x00\x00\x00\x00\x00ABC\xce\x94", ) self.assertEqual( bincode.deserialize(b"\x05\x00\x00\x00\x00\x00\x00\x00ABC\xce\x94A", str), ("ABC\u0394", b"A"), ) with self.assertRaises(st.DeserializationError): bincode.deserialize(b"\x03\x00\x00\x00\x00\x00\x00\x00AB", str) with self.assertRaises(st.DeserializationError): bincode.deserialize(b"\x03\x00\x00\x00\x00\x00\x00\x00\x80ab", str) def test_serialize_map(self): Map = typing.Dict[st.uint16, st.uint8] m = OrderedDict([(256, 3), (1, 5)]) e = bincode.serialize(m, Map) self.assertEqual(e, b"\x02\x00\x00\x00\x00\x00\x00\x00\x00\x01\x03\x01\x00\x05") self.assertEqual( (m, b""), bincode.deserialize( b"\x02\x00\x00\x00\x00\x00\x00\x00\x00\x01\x03\x01\x00\x05", Map ), ) self.assertEqual( (m, b""), bincode.deserialize( b"\x02\x00\x00\x00\x00\x00\x00\x00\x01\x00\x05\x00\x01\x03", Map ), ) m2 = OrderedDict([(1, 5), (256, 3)]) e2 = bincode.serialize(m2, Map) self.assertEqual( e2, b"\x02\x00\x00\x00\x00\x00\x00\x00\x01\x00\x05\x00\x01\x03" ) def test_serialize_set(self): Set = typing.Dict[st.uint16, st.unit] m = {256: None, 1: None} e = bincode.serialize(m, Set) self.assertEqual(e, b"\x02\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01\x00") self.assertEqual( (m, b""), bincode.deserialize( b"\x02\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01\x00", Set ), ) self.assertEqual( (m, b""), bincode.deserialize( b"\x02\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x01", Set ), ) @dataclass class Foo: x: st.uint8 y: st.uint16 def test_struct(self): self.assertEqual( bincode.serialize(BincodeTestCase.Foo(x=0, y=1), BincodeTestCase.Foo), b"\x00\x01\x00", ) self.assertEqual( bincode.deserialize(b"\x02\x01\x00", BincodeTestCase.Foo), (BincodeTestCase.Foo(x=2, y=1), b""), ) class Bar: VARIANTS = [] # type: typing.Sequence[typing.Type['Bar']] @dataclass class Bar1(Bar): INDEX = 1 x: st.uint8 y: st.uint16 Bar.VARIANTS = [None, Bar1, None] def test_enum(self): self.assertEqual( bincode.serialize(BincodeTestCase.Bar1(x=0, y=1), BincodeTestCase.Bar), b"\x01\x00\x00\x00\x00\x01\x00", ) self.assertEqual( bincode.deserialize(b"\x01\x00\x00\x00\x02\x01\x00", BincodeTestCase.Bar), (BincodeTestCase.Bar1(x=2, y=1), b""), )