import fbe
import datetime
import decimal
import uuid
import proto
from proto import proto
from proto import test
from unittest import TestCase


class TestSerializationFinal(TestCase):

    def test_serialization_final_domain(self):
        # Create a new account with some orders
        account1 = proto.Account(1, "Test", proto.State.good, proto.Balance("USD", 1000.0), proto.Balance("EUR", 100.0))
        account1.orders.append(proto.Order(1, "EURUSD", proto.OrderSide.buy, proto.OrderType.market, 1.23456, 1000.0))
        account1.orders.append(proto.Order(2, "EURUSD", proto.OrderSide.sell, proto.OrderType.limit, 1.0, 100.0))
        account1.orders.append(proto.Order(3, "EURUSD", proto.OrderSide.buy, proto.OrderType.stop, 1.5, 10.0))

        # Serialize the account to the FBE stream
        writer = proto.AccountFinalModel(fbe.WriteBuffer())
        serialized = writer.serialize(account1)
        self.assertEqual(serialized, writer.buffer.size)
        self.assertTrue(writer.verify())
        writer.next(serialized)

        # Check the serialized FBE size
        self.assertEqual(writer.buffer.size, 152)

        # Deserialize the account from the FBE stream
        account2 = proto.Account()
        reader = proto.AccountFinalModel(fbe.ReadBuffer())
        reader.attach_buffer(writer.buffer)
        self.assertTrue(reader.verify())
        (account2, deserialized) = reader.deserialize(account2)
        self.assertEqual(deserialized, reader.buffer.size)
        reader.next(deserialized)

        self.assertEqual(account2.id, 1)
        self.assertEqual(account2.name, "Test")
        self.assertTrue(account2.state.has_flags(proto.State.good))
        self.assertEqual(account2.wallet.currency, "USD")
        self.assertEqual(account2.wallet.amount, 1000.0)
        self.assertNotEqual(account2.asset, None)
        self.assertEqual(account2.asset.currency, "EUR")
        self.assertEqual(account2.asset.amount, 100.0)
        self.assertEqual(len(account2.orders), 3)
        self.assertEqual(account2.orders[0].id, 1)
        self.assertEqual(account2.orders[0].symbol, "EURUSD")
        self.assertEqual(account2.orders[0].side, proto.OrderSide.buy)
        self.assertEqual(account2.orders[0].type, proto.OrderType.market)
        self.assertEqual(account2.orders[0].price, 1.23456)
        self.assertEqual(account2.orders[0].volume, 1000.0)
        self.assertEqual(account2.orders[1].id, 2)
        self.assertEqual(account2.orders[1].symbol, "EURUSD")
        self.assertEqual(account2.orders[1].side, proto.OrderSide.sell)
        self.assertEqual(account2.orders[1].type, proto.OrderType.limit)
        self.assertEqual(account2.orders[1].price, 1.0)
        self.assertEqual(account2.orders[1].volume, 100.0)
        self.assertEqual(account2.orders[2].id, 3)
        self.assertEqual(account2.orders[2].symbol, "EURUSD")
        self.assertEqual(account2.orders[2].side, proto.OrderSide.buy)
        self.assertEqual(account2.orders[2].type, proto.OrderType.stop)
        self.assertEqual(account2.orders[2].price, 1.5)
        self.assertEqual(account2.orders[2].volume, 10.0)

    def test_serialization_final_struct_simple(self):
        # Create a new struct
        struct1 = test.StructSimple()

        # Serialize the struct to the FBE stream
        writer = test.StructSimpleFinalModel(fbe.WriteBuffer())
        self.assertEqual(writer.fbe_type, 110)
        serialized = writer.serialize(struct1)
        self.assertEqual(serialized, writer.buffer.size)
        self.assertTrue(writer.verify())
        writer.next(serialized)

        # Check the serialized FBE size
        self.assertEqual(writer.buffer.size, 304)

        # Deserialize the struct from the FBE stream
        struct2 = test.StructSimple()
        reader = test.StructSimpleFinalModel(fbe.ReadBuffer())
        self.assertEqual(reader.fbe_type, 110)
        reader.attach_buffer(writer.buffer)
        self.assertTrue(reader.verify())
        (struct2, deserialized) = reader.deserialize(struct2)
        self.assertEqual(deserialized, reader.buffer.size)
        reader.next(deserialized)

        self.assertEqual(struct2.f1, False)
        self.assertEqual(struct2.f2, True)
        self.assertEqual(struct2.f3, 0)
        self.assertEqual(struct2.f4, 0xFF)
        self.assertEqual(struct2.f5, '\0')
        self.assertEqual(struct2.f6, '!')
        self.assertEqual(struct2.f7, chr(0))
        self.assertEqual(struct2.f8, chr(0x0444))
        self.assertEqual(struct2.f9, 0)
        self.assertEqual(struct2.f10, 127)
        self.assertEqual(struct2.f11, 0)
        self.assertEqual(struct2.f12, 0xFF)
        self.assertEqual(struct2.f13, 0)
        self.assertEqual(struct2.f14, 32767)
        self.assertEqual(struct2.f15, 0)
        self.assertEqual(struct2.f16, 0xFFFF)
        self.assertEqual(struct2.f17, 0)
        self.assertEqual(struct2.f18, 2147483647)
        self.assertEqual(struct2.f19, 0)
        self.assertEqual(struct2.f20, 0xFFFFFFFF)
        self.assertEqual(struct2.f21, 0)
        self.assertEqual(struct2.f22, 9223372036854775807)
        self.assertEqual(struct2.f23, 0)
        self.assertEqual(struct2.f24, 0xFFFFFFFFFFFFFFFF)
        self.assertEqual(struct2.f25, 0.0)
        self.assertLess(abs(struct2.f26 - 123.456), 0.0001)
        self.assertEqual(struct2.f27, 0.0)
        self.assertLess(abs(struct2.f28 - -123.567e+123), 1e+123)
        self.assertEqual(struct2.f29, decimal.Decimal("0"))
        self.assertEqual(struct2.f30, decimal.Decimal("123456.123456"))
        self.assertEqual(struct2.f31, "")
        self.assertEqual(struct2.f32, "Initial string!")
        self.assertEqual(datetime.datetime.utcfromtimestamp(struct2.f33 / 1000000000), datetime.datetime(1970, 1, 1))
        self.assertEqual(datetime.datetime.utcfromtimestamp(struct2.f34 / 1000000000), datetime.datetime(1970, 1, 1))
        self.assertGreater(datetime.datetime.utcfromtimestamp(struct2.f35 / 1000000000), datetime.datetime(2018, 1, 1))
        self.assertEqual(struct2.f36, uuid.UUID(int=0))
        self.assertNotEqual(struct2.f37, uuid.UUID(int=0))
        self.assertEqual(struct2.f38, uuid.UUID("123e4567-e89b-12d3-a456-426655440000"))

        self.assertEqual(struct2.f1, struct1.f1)
        self.assertEqual(struct2.f2, struct1.f2)
        self.assertEqual(struct2.f3, struct1.f3)
        self.assertEqual(struct2.f4, struct1.f4)
        self.assertEqual(struct2.f5, struct1.f5)
        self.assertEqual(struct2.f6, struct1.f6)
        self.assertEqual(struct2.f7, struct1.f7)
        self.assertEqual(struct2.f8, struct1.f8)
        self.assertEqual(struct2.f9, struct1.f9)
        self.assertEqual(struct2.f10, struct1.f10)
        self.assertEqual(struct2.f11, struct1.f11)
        self.assertEqual(struct2.f12, struct1.f12)
        self.assertEqual(struct2.f13, struct1.f13)
        self.assertEqual(struct2.f14, struct1.f14)
        self.assertEqual(struct2.f15, struct1.f15)
        self.assertEqual(struct2.f16, struct1.f16)
        self.assertEqual(struct2.f17, struct1.f17)
        self.assertEqual(struct2.f18, struct1.f18)
        self.assertEqual(struct2.f19, struct1.f19)
        self.assertEqual(struct2.f20, struct1.f20)
        self.assertEqual(struct2.f21, struct1.f21)
        self.assertEqual(struct2.f22, struct1.f22)
        self.assertEqual(struct2.f23, struct1.f23)
        self.assertEqual(struct2.f24, struct1.f24)
        self.assertEqual(struct2.f25, struct1.f25)
        self.assertLess(abs(struct2.f26 - struct1.f26), 0.0001)
        self.assertEqual(struct2.f27, struct1.f27)
        self.assertLess(abs(struct2.f28 - struct1.f28), 1e+123)
        self.assertEqual(struct2.f29, struct1.f29)
        self.assertEqual(struct2.f30, struct1.f30)
        self.assertEqual(struct2.f31, struct1.f31)
        self.assertEqual(struct2.f32, struct1.f32)
        self.assertEqual(struct2.f33, struct1.f33)
        self.assertEqual(struct2.f34, struct1.f34)
        self.assertEqual(struct2.f35, struct1.f35)
        self.assertEqual(struct2.f36, struct1.f36)
        self.assertEqual(struct2.f37, struct1.f37)
        self.assertEqual(struct2.f38, struct1.f38)
        self.assertEqual(struct2.f39, struct1.f39)
        self.assertEqual(struct2.f40, struct1.f40)

    def test_serialization_final_struct_optional(self):
        # Create a new struct
        struct1 = test.StructOptional()

        # Serialize the struct to the FBE stream
        writer = test.StructOptionalFinalModel(fbe.WriteBuffer())
        self.assertEqual(writer.fbe_type, 111)
        serialized = writer.serialize(struct1)
        self.assertEqual(serialized, writer.buffer.size)
        self.assertTrue(writer.verify())
        writer.next(serialized)

        # Check the serialized FBE size
        self.assertEqual(writer.buffer.size, 478)

        # Deserialize the struct from the FBE stream
        struct2 = test.StructOptional()
        reader = test.StructOptionalFinalModel(fbe.ReadBuffer())
        self.assertEqual(reader.fbe_type, 111)
        reader.attach_buffer(writer.buffer)
        self.assertTrue(reader.verify())
        (struct2, deserialized) = reader.deserialize(struct2)
        self.assertEqual(deserialized, reader.buffer.size)
        reader.next(deserialized)

        self.assertEqual(struct2.f1, False)
        self.assertEqual(struct2.f2, True)
        self.assertEqual(struct2.f3, 0)
        self.assertEqual(struct2.f4, 0xFF)
        self.assertEqual(struct2.f5, '\0')
        self.assertEqual(struct2.f6, '!')
        self.assertEqual(struct2.f7, chr(0))
        self.assertEqual(struct2.f8, chr(0x0444))
        self.assertEqual(struct2.f9, 0)
        self.assertEqual(struct2.f10, 127)
        self.assertEqual(struct2.f11, 0)
        self.assertEqual(struct2.f12, 0xFF)
        self.assertEqual(struct2.f13, 0)
        self.assertEqual(struct2.f14, 32767)
        self.assertEqual(struct2.f15, 0)
        self.assertEqual(struct2.f16, 0xFFFF)
        self.assertEqual(struct2.f17, 0)
        self.assertEqual(struct2.f18, 2147483647)
        self.assertEqual(struct2.f19, 0)
        self.assertEqual(struct2.f20, 0xFFFFFFFF)
        self.assertEqual(struct2.f21, 0)
        self.assertEqual(struct2.f22, 9223372036854775807)
        self.assertEqual(struct2.f23, 0)
        self.assertEqual(struct2.f24, 0xFFFFFFFFFFFFFFFF)
        self.assertEqual(struct2.f25, 0.0)
        self.assertLess(abs(struct2.f26 - 123.456), 0.0001)
        self.assertEqual(struct2.f27, 0.0)
        self.assertLess(abs(struct2.f28 - -123.567e+123), 1e+123)
        self.assertEqual(struct2.f29, decimal.Decimal("0"))
        self.assertEqual(struct2.f30, decimal.Decimal("123456.123456"))
        self.assertEqual(struct2.f31, "")
        self.assertEqual(struct2.f32, "Initial string!")
        self.assertEqual(datetime.datetime.utcfromtimestamp(struct2.f33 / 1000000000), datetime.datetime(1970, 1, 1))
        self.assertEqual(datetime.datetime.utcfromtimestamp(struct2.f34 / 1000000000), datetime.datetime(1970, 1, 1))
        self.assertGreater(datetime.datetime.utcfromtimestamp(struct2.f35 / 1000000000), datetime.datetime(2018, 1, 1))
        self.assertEqual(struct2.f36, uuid.UUID(int=0))
        self.assertNotEqual(struct2.f37, uuid.UUID(int=0))
        self.assertEqual(struct2.f38, uuid.UUID("123e4567-e89b-12d3-a456-426655440000"))

        self.assertEqual(struct2.f100, None)
        self.assertNotEqual(struct2.f101, None)
        self.assertEqual(struct2.f101, True)
        self.assertEqual(struct2.f102, None)
        self.assertEqual(struct2.f103, None)
        self.assertNotEqual(struct2.f104, None)
        self.assertEqual(struct2.f104, 0xFF)
        self.assertEqual(struct2.f105, None)
        self.assertEqual(struct2.f106, None)
        self.assertNotEqual(struct2.f107, None)
        self.assertEqual(struct2.f107, '!')
        self.assertEqual(struct2.f108, None)
        self.assertEqual(struct2.f109, None)
        self.assertNotEqual(struct2.f110, None)
        self.assertEqual(struct2.f110, chr(0x0444))
        self.assertEqual(struct2.f111, None)
        self.assertEqual(struct2.f112, None)
        self.assertNotEqual(struct2.f113, None)
        self.assertEqual(struct2.f113, 127)
        self.assertEqual(struct2.f114, None)
        self.assertEqual(struct2.f115, None)
        self.assertNotEqual(struct2.f116, None)
        self.assertEqual(struct2.f116, 0xFF)
        self.assertEqual(struct2.f117, None)
        self.assertEqual(struct2.f118, None)
        self.assertNotEqual(struct2.f119, None)
        self.assertEqual(struct2.f119, 32767)
        self.assertEqual(struct2.f120, None)
        self.assertEqual(struct2.f121, None)
        self.assertNotEqual(struct2.f122, None)
        self.assertEqual(struct2.f122, 0xFFFF)
        self.assertEqual(struct2.f123, None)
        self.assertEqual(struct2.f124, None)
        self.assertNotEqual(struct2.f125, None)
        self.assertEqual(struct2.f125, 2147483647)
        self.assertEqual(struct2.f126, None)
        self.assertEqual(struct2.f127, None)
        self.assertNotEqual(struct2.f128, None)
        self.assertEqual(struct2.f128, 0xFFFFFFFF)
        self.assertEqual(struct2.f129, None)
        self.assertEqual(struct2.f130, None)
        self.assertNotEqual(struct2.f131, None)
        self.assertEqual(struct2.f131, 9223372036854775807)
        self.assertEqual(struct2.f132, None)
        self.assertEqual(struct2.f133, None)
        self.assertNotEqual(struct2.f131, None)
        self.assertEqual(struct2.f134, 0xFFFFFFFFFFFFFFFF)
        self.assertEqual(struct2.f135, None)
        self.assertEqual(struct2.f136, None)
        self.assertNotEqual(struct2.f137, None)
        self.assertLess(abs(struct2.f137 - 123.456), 0.0001)
        self.assertEqual(struct2.f138, None)
        self.assertEqual(struct2.f139, None)
        self.assertNotEqual(struct2.f140, None)
        self.assertLess(abs(struct2.f140 - -123.567e+123), 1e+123)
        self.assertEqual(struct2.f141, None)
        self.assertEqual(struct2.f142, None)
        self.assertNotEqual(struct2.f143, None)
        self.assertEqual(struct2.f143, decimal.Decimal("123456.123456"))
        self.assertEqual(struct2.f144, None)
        self.assertEqual(struct2.f145, None)
        self.assertNotEqual(struct2.f146, None)
        self.assertEqual(struct2.f146, "Initial string!")
        self.assertEqual(struct2.f147, None)
        self.assertEqual(struct2.f148, None)
        self.assertNotEqual(struct2.f149, None)
        self.assertGreater(datetime.datetime.utcfromtimestamp(struct2.f149 / 1000000000), datetime.datetime(2018, 1, 1))
        self.assertEqual(struct2.f150, None)
        self.assertEqual(struct2.f151, None)
        self.assertNotEqual(struct2.f152, None)
        self.assertEqual(struct2.f152, uuid.UUID("123e4567-e89b-12d3-a456-426655440000"))
        self.assertEqual(struct2.f153, None)
        self.assertEqual(struct2.f154, None)
        self.assertEqual(struct2.f155, None)
        self.assertEqual(struct2.f156, None)
        self.assertEqual(struct2.f157, None)
        self.assertEqual(struct2.f158, None)
        self.assertEqual(struct2.f159, None)
        self.assertEqual(struct2.f160, None)
        self.assertEqual(struct2.f161, None)
        self.assertEqual(struct2.f162, None)
        self.assertEqual(struct2.f163, None)
        self.assertEqual(struct2.f164, None)
        self.assertEqual(struct2.f165, None)

        self.assertEqual(struct2.f1, struct1.f1)
        self.assertEqual(struct2.f2, struct1.f2)
        self.assertEqual(struct2.f3, struct1.f3)
        self.assertEqual(struct2.f4, struct1.f4)
        self.assertEqual(struct2.f5, struct1.f5)
        self.assertEqual(struct2.f6, struct1.f6)
        self.assertEqual(struct2.f7, struct1.f7)
        self.assertEqual(struct2.f8, struct1.f8)
        self.assertEqual(struct2.f9, struct1.f9)
        self.assertEqual(struct2.f10, struct1.f10)
        self.assertEqual(struct2.f11, struct1.f11)
        self.assertEqual(struct2.f12, struct1.f12)
        self.assertEqual(struct2.f13, struct1.f13)
        self.assertEqual(struct2.f14, struct1.f14)
        self.assertEqual(struct2.f15, struct1.f15)
        self.assertEqual(struct2.f16, struct1.f16)
        self.assertEqual(struct2.f17, struct1.f17)
        self.assertEqual(struct2.f18, struct1.f18)
        self.assertEqual(struct2.f19, struct1.f19)
        self.assertEqual(struct2.f20, struct1.f20)
        self.assertEqual(struct2.f21, struct1.f21)
        self.assertEqual(struct2.f22, struct1.f22)
        self.assertEqual(struct2.f23, struct1.f23)
        self.assertEqual(struct2.f24, struct1.f24)
        self.assertEqual(struct2.f25, struct1.f25)
        self.assertLess(abs(struct2.f26 - struct1.f26), 0.0001)
        self.assertEqual(struct2.f27, struct1.f27)
        self.assertLess(abs(struct2.f28 - struct1.f28), 1e+123)
        self.assertEqual(struct2.f29, struct1.f29)
        self.assertEqual(struct2.f30, struct1.f30)
        self.assertEqual(struct2.f31, struct1.f31)
        self.assertEqual(struct2.f32, struct1.f32)
        self.assertEqual(struct2.f33, struct1.f33)
        self.assertEqual(struct2.f34, struct1.f34)
        self.assertEqual(struct2.f35, struct1.f35)
        self.assertEqual(struct2.f36, struct1.f36)
        self.assertEqual(struct2.f37, struct1.f37)

        self.assertEqual(struct2.f100, struct1.f100)
        self.assertEqual(struct2.f101, struct1.f101)
        self.assertEqual(struct2.f102, struct1.f102)
        self.assertEqual(struct2.f103, struct1.f103)
        self.assertEqual(struct2.f104, struct1.f104)
        self.assertEqual(struct2.f105, struct1.f105)
        self.assertEqual(struct2.f106, struct1.f106)
        self.assertEqual(struct2.f107, struct1.f107)
        self.assertEqual(struct2.f108, struct1.f108)
        self.assertEqual(struct2.f109, struct1.f109)
        self.assertEqual(struct2.f110, struct1.f110)
        self.assertEqual(struct2.f111, struct1.f111)
        self.assertEqual(struct2.f112, struct1.f112)
        self.assertEqual(struct2.f113, struct1.f113)
        self.assertEqual(struct2.f114, struct1.f114)
        self.assertEqual(struct2.f115, struct1.f115)
        self.assertEqual(struct2.f116, struct1.f116)
        self.assertEqual(struct2.f117, struct1.f117)
        self.assertEqual(struct2.f118, struct1.f118)
        self.assertEqual(struct2.f119, struct1.f119)
        self.assertEqual(struct2.f120, struct1.f120)
        self.assertEqual(struct2.f121, struct1.f121)
        self.assertEqual(struct2.f122, struct1.f122)
        self.assertEqual(struct2.f123, struct1.f123)
        self.assertEqual(struct2.f124, struct1.f124)
        self.assertEqual(struct2.f125, struct1.f125)
        self.assertEqual(struct2.f126, struct1.f126)
        self.assertEqual(struct2.f127, struct1.f127)
        self.assertEqual(struct2.f128, struct1.f128)
        self.assertEqual(struct2.f129, struct1.f129)
        self.assertEqual(struct2.f130, struct1.f130)
        self.assertEqual(struct2.f131, struct1.f131)
        self.assertEqual(struct2.f132, struct1.f132)
        self.assertEqual(struct2.f133, struct1.f133)
        self.assertEqual(struct2.f134, struct1.f134)
        self.assertEqual(struct2.f135, struct1.f135)
        self.assertEqual(struct2.f136, struct1.f136)
        self.assertLess(abs(struct2.f137 - struct1.f137), 0.0001)
        self.assertEqual(struct2.f138, struct1.f138)
        self.assertEqual(struct2.f139, struct1.f139)
        self.assertLess(abs(struct2.f140 - struct1.f140), 1e+123)
        self.assertEqual(struct2.f141, struct1.f141)
        self.assertEqual(struct2.f142, struct1.f142)
        self.assertEqual(struct2.f143, struct1.f143)
        self.assertEqual(struct2.f144, struct1.f144)
        self.assertEqual(struct2.f145, struct1.f145)
        self.assertEqual(struct2.f146, struct1.f146)
        self.assertEqual(struct2.f147, struct1.f147)
        self.assertEqual(struct2.f148, struct1.f148)
        self.assertEqual(struct2.f149, struct1.f149)
        self.assertEqual(struct2.f150, struct1.f150)
        self.assertEqual(struct2.f151, struct1.f151)
        self.assertEqual(struct2.f152, struct1.f152)
        self.assertEqual(struct2.f153, struct1.f153)
        self.assertEqual(struct2.f154, struct1.f154)
        self.assertEqual(struct2.f155, struct1.f155)
        self.assertEqual(struct2.f156, struct1.f156)
        self.assertEqual(struct2.f157, struct1.f157)

    def test_serialization_final_struct_nested(self):
        # Create a new struct
        struct1 = test.StructNested()

        # Serialize the struct to the FBE stream
        writer = test.StructNestedFinalModel(fbe.WriteBuffer())
        self.assertEqual(writer.fbe_type, 112)
        serialized = writer.serialize(struct1)
        self.assertEqual(serialized, writer.buffer.size)
        self.assertTrue(writer.verify())
        writer.next(serialized)

        # Check the serialized FBE size
        self.assertEqual(writer.buffer.size, 1267)

        # Deserialize the struct from the FBE stream
        struct2 = test.StructNested()
        reader = test.StructNestedFinalModel(fbe.ReadBuffer())
        self.assertEqual(reader.fbe_type, 112)
        reader.attach_buffer(writer.buffer)
        self.assertTrue(reader.verify())
        (struct2, deserialized) = reader.deserialize(struct2)
        self.assertEqual(deserialized, reader.buffer.size)
        reader.next(deserialized)

        self.assertEqual(struct2.f1, False)
        self.assertEqual(struct2.f2, True)
        self.assertEqual(struct2.f3, 0)
        self.assertEqual(struct2.f4, 0xFF)
        self.assertEqual(struct2.f5, '\0')
        self.assertEqual(struct2.f6, '!')
        self.assertEqual(struct2.f7, chr(0))
        self.assertEqual(struct2.f8, chr(0x0444))
        self.assertEqual(struct2.f9, 0)
        self.assertEqual(struct2.f10, 127)
        self.assertEqual(struct2.f11, 0)
        self.assertEqual(struct2.f12, 0xFF)
        self.assertEqual(struct2.f13, 0)
        self.assertEqual(struct2.f14, 32767)
        self.assertEqual(struct2.f15, 0)
        self.assertEqual(struct2.f16, 0xFFFF)
        self.assertEqual(struct2.f17, 0)
        self.assertEqual(struct2.f18, 2147483647)
        self.assertEqual(struct2.f19, 0)
        self.assertEqual(struct2.f20, 0xFFFFFFFF)
        self.assertEqual(struct2.f21, 0)
        self.assertEqual(struct2.f22, 9223372036854775807)
        self.assertEqual(struct2.f23, 0)
        self.assertEqual(struct2.f24, 0xFFFFFFFFFFFFFFFF)
        self.assertEqual(struct2.f25, 0.0)
        self.assertLess(abs(struct2.f26 - 123.456), 0.0001)
        self.assertEqual(struct2.f27, 0.0)
        self.assertLess(abs(struct2.f28 - -123.567e+123), 1e+123)
        self.assertEqual(struct2.f29, decimal.Decimal("0"))
        self.assertEqual(struct2.f30, decimal.Decimal("123456.123456"))
        self.assertEqual(struct2.f31, "")
        self.assertEqual(struct2.f32, "Initial string!")
        self.assertEqual(datetime.datetime.utcfromtimestamp(struct2.f33 / 1000000000), datetime.datetime(1970, 1, 1))
        self.assertEqual(datetime.datetime.utcfromtimestamp(struct2.f34 / 1000000000), datetime.datetime(1970, 1, 1))
        self.assertGreater(datetime.datetime.utcfromtimestamp(struct2.f35 / 1000000000), datetime.datetime(2018, 1, 1))
        self.assertEqual(struct2.f36, uuid.UUID(int=0))
        self.assertNotEqual(struct2.f37, uuid.UUID(int=0))
        self.assertEqual(struct2.f38, uuid.UUID("123e4567-e89b-12d3-a456-426655440000"))

        self.assertEqual(struct2.f100, None)
        self.assertNotEqual(struct2.f101, None)
        self.assertEqual(struct2.f101, True)
        self.assertEqual(struct2.f102, None)
        self.assertEqual(struct2.f103, None)
        self.assertNotEqual(struct2.f104, None)
        self.assertEqual(struct2.f104, 0xFF)
        self.assertEqual(struct2.f105, None)
        self.assertEqual(struct2.f106, None)
        self.assertNotEqual(struct2.f107, None)
        self.assertEqual(struct2.f107, '!')
        self.assertEqual(struct2.f108, None)
        self.assertEqual(struct2.f109, None)
        self.assertNotEqual(struct2.f110, None)
        self.assertEqual(struct2.f110, chr(0x0444))
        self.assertEqual(struct2.f111, None)
        self.assertEqual(struct2.f112, None)
        self.assertNotEqual(struct2.f113, None)
        self.assertEqual(struct2.f113, 127)
        self.assertEqual(struct2.f114, None)
        self.assertEqual(struct2.f115, None)
        self.assertNotEqual(struct2.f116, None)
        self.assertEqual(struct2.f116, 0xFF)
        self.assertEqual(struct2.f117, None)
        self.assertEqual(struct2.f118, None)
        self.assertNotEqual(struct2.f119, None)
        self.assertEqual(struct2.f119, 32767)
        self.assertEqual(struct2.f120, None)
        self.assertEqual(struct2.f121, None)
        self.assertNotEqual(struct2.f122, None)
        self.assertEqual(struct2.f122, 0xFFFF)
        self.assertEqual(struct2.f123, None)
        self.assertEqual(struct2.f124, None)
        self.assertNotEqual(struct2.f125, None)
        self.assertEqual(struct2.f125, 2147483647)
        self.assertEqual(struct2.f126, None)
        self.assertEqual(struct2.f127, None)
        self.assertNotEqual(struct2.f128, None)
        self.assertEqual(struct2.f128, 0xFFFFFFFF)
        self.assertEqual(struct2.f129, None)
        self.assertEqual(struct2.f130, None)
        self.assertNotEqual(struct2.f131, None)
        self.assertEqual(struct2.f131, 9223372036854775807)
        self.assertEqual(struct2.f132, None)
        self.assertEqual(struct2.f133, None)
        self.assertNotEqual(struct2.f131, None)
        self.assertEqual(struct2.f134, 0xFFFFFFFFFFFFFFFF)
        self.assertEqual(struct2.f135, None)
        self.assertEqual(struct2.f136, None)
        self.assertNotEqual(struct2.f137, None)
        self.assertLess(abs(struct2.f137 - 123.456), 0.0001)
        self.assertEqual(struct2.f138, None)
        self.assertEqual(struct2.f139, None)
        self.assertNotEqual(struct2.f140, None)
        self.assertLess(abs(struct2.f140 - -123.567e+123), 1e+123)
        self.assertEqual(struct2.f141, None)
        self.assertEqual(struct2.f142, None)
        self.assertNotEqual(struct2.f143, None)
        self.assertEqual(struct2.f143, decimal.Decimal("123456.123456"))
        self.assertEqual(struct2.f144, None)
        self.assertEqual(struct2.f145, None)
        self.assertNotEqual(struct2.f146, None)
        self.assertEqual(struct2.f146, "Initial string!")
        self.assertEqual(struct2.f147, None)
        self.assertEqual(struct2.f148, None)
        self.assertNotEqual(struct2.f149, None)
        self.assertGreater(datetime.datetime.utcfromtimestamp(struct2.f149 / 1000000000), datetime.datetime(2018, 1, 1))
        self.assertEqual(struct2.f150, None)
        self.assertEqual(struct2.f151, None)
        self.assertNotEqual(struct2.f152, None)
        self.assertEqual(struct2.f152, uuid.UUID("123e4567-e89b-12d3-a456-426655440000"))
        self.assertEqual(struct2.f153, None)
        self.assertEqual(struct2.f154, None)
        self.assertEqual(struct2.f155, None)
        self.assertEqual(struct2.f156, None)
        self.assertEqual(struct2.f157, None)
        self.assertEqual(struct2.f158, None)
        self.assertEqual(struct2.f159, None)
        self.assertEqual(struct2.f160, None)
        self.assertEqual(struct2.f161, None)
        self.assertEqual(struct2.f162, None)
        self.assertEqual(struct2.f163, None)
        self.assertEqual(struct2.f164, None)
        self.assertEqual(struct2.f165, None)

        self.assertEqual(struct2.f1000, test.EnumSimple.ENUM_VALUE_0)
        self.assertEqual(struct2.f1001, None)
        self.assertEqual(struct2.f1002, test.EnumTyped.ENUM_VALUE_2)
        self.assertEqual(struct2.f1003, None)
        self.assertEqual(struct2.f1004, test.FlagsSimple.FLAG_VALUE_0)
        self.assertEqual(struct2.f1005, None)
        self.assertEqual(struct2.f1006, test.FlagsTyped.FLAG_VALUE_2 | test.FlagsTyped.FLAG_VALUE_4 | test.FlagsTyped.FLAG_VALUE_6)
        self.assertEqual(struct2.f1007, None)
        self.assertEqual(struct2.f1009, None)
        self.assertEqual(struct2.f1011, None)

        self.assertEqual(struct2.f1, struct1.f1)
        self.assertEqual(struct2.f2, struct1.f2)
        self.assertEqual(struct2.f3, struct1.f3)
        self.assertEqual(struct2.f4, struct1.f4)
        self.assertEqual(struct2.f5, struct1.f5)
        self.assertEqual(struct2.f6, struct1.f6)
        self.assertEqual(struct2.f7, struct1.f7)
        self.assertEqual(struct2.f8, struct1.f8)
        self.assertEqual(struct2.f9, struct1.f9)
        self.assertEqual(struct2.f10, struct1.f10)
        self.assertEqual(struct2.f11, struct1.f11)
        self.assertEqual(struct2.f12, struct1.f12)
        self.assertEqual(struct2.f13, struct1.f13)
        self.assertEqual(struct2.f14, struct1.f14)
        self.assertEqual(struct2.f15, struct1.f15)
        self.assertEqual(struct2.f16, struct1.f16)
        self.assertEqual(struct2.f17, struct1.f17)
        self.assertEqual(struct2.f18, struct1.f18)
        self.assertEqual(struct2.f19, struct1.f19)
        self.assertEqual(struct2.f20, struct1.f20)
        self.assertEqual(struct2.f21, struct1.f21)
        self.assertEqual(struct2.f22, struct1.f22)
        self.assertEqual(struct2.f23, struct1.f23)
        self.assertEqual(struct2.f24, struct1.f24)
        self.assertEqual(struct2.f25, struct1.f25)
        self.assertLess(abs(struct2.f26 - struct1.f26), 0.0001)
        self.assertEqual(struct2.f27, struct1.f27)
        self.assertLess(abs(struct2.f28 - struct2.f28), 1e+123)
        self.assertEqual(struct2.f29, struct1.f29)
        self.assertEqual(struct2.f30, struct1.f30)
        self.assertEqual(struct2.f31, struct1.f31)
        self.assertEqual(struct2.f32, struct1.f32)
        self.assertEqual(struct2.f33, struct1.f33)
        self.assertEqual(struct2.f34, struct1.f34)
        self.assertEqual(struct2.f35, struct1.f35)
        self.assertEqual(struct2.f36, struct1.f36)
        self.assertEqual(struct2.f37, struct1.f37)
        self.assertEqual(struct2.f38, struct1.f38)
        self.assertEqual(struct2.f39, struct1.f39)
        self.assertEqual(struct2.f40, struct1.f40)

        self.assertEqual(struct2.f100, struct1.f100)
        self.assertEqual(struct2.f101, struct1.f101)
        self.assertEqual(struct2.f102, struct1.f102)
        self.assertEqual(struct2.f103, struct1.f103)
        self.assertEqual(struct2.f104, struct1.f104)
        self.assertEqual(struct2.f105, struct1.f105)
        self.assertEqual(struct2.f106, struct1.f106)
        self.assertEqual(struct2.f107, struct1.f107)
        self.assertEqual(struct2.f108, struct1.f108)
        self.assertEqual(struct2.f109, struct1.f109)
        self.assertEqual(struct2.f110, struct1.f110)
        self.assertEqual(struct2.f111, struct1.f111)
        self.assertEqual(struct2.f112, struct1.f112)
        self.assertEqual(struct2.f113, struct1.f113)
        self.assertEqual(struct2.f114, struct1.f114)
        self.assertEqual(struct2.f115, struct1.f115)
        self.assertEqual(struct2.f116, struct1.f116)
        self.assertEqual(struct2.f117, struct1.f117)
        self.assertEqual(struct2.f118, struct1.f118)
        self.assertEqual(struct2.f119, struct1.f119)
        self.assertEqual(struct2.f120, struct1.f120)
        self.assertEqual(struct2.f121, struct1.f121)
        self.assertEqual(struct2.f122, struct1.f122)
        self.assertEqual(struct2.f123, struct1.f123)
        self.assertEqual(struct2.f124, struct1.f124)
        self.assertEqual(struct2.f125, struct1.f125)
        self.assertEqual(struct2.f126, struct1.f126)
        self.assertEqual(struct2.f127, struct1.f127)
        self.assertEqual(struct2.f128, struct1.f128)
        self.assertEqual(struct2.f129, struct1.f129)
        self.assertEqual(struct2.f130, struct1.f130)
        self.assertEqual(struct2.f131, struct1.f131)
        self.assertEqual(struct2.f132, struct1.f132)
        self.assertEqual(struct2.f133, struct1.f133)
        self.assertEqual(struct2.f134, struct1.f134)
        self.assertEqual(struct2.f135, struct1.f135)
        self.assertEqual(struct2.f136, struct1.f136)
        self.assertLess(abs(struct2.f137 - struct1.f137), 0.0001)
        self.assertEqual(struct2.f138, struct1.f138)
        self.assertEqual(struct2.f139, struct1.f139)
        self.assertLess(abs(struct2.f140 - struct1.f140), 1e+123)
        self.assertEqual(struct2.f141, struct1.f141)
        self.assertEqual(struct2.f142, struct1.f142)
        self.assertEqual(struct2.f143, struct1.f143)
        self.assertEqual(struct2.f144, struct1.f144)
        self.assertEqual(struct2.f145, struct1.f145)
        self.assertEqual(struct2.f146, struct1.f146)
        self.assertEqual(struct2.f147, struct1.f147)
        self.assertEqual(struct2.f148, struct1.f148)
        self.assertEqual(struct2.f149, struct1.f149)
        self.assertEqual(struct2.f150, struct1.f150)
        self.assertEqual(struct2.f151, struct1.f151)
        self.assertEqual(struct2.f152, struct1.f152)
        self.assertEqual(struct2.f153, struct1.f153)
        self.assertEqual(struct2.f154, struct1.f154)
        self.assertEqual(struct2.f155, struct1.f155)
        self.assertEqual(struct2.f156, struct1.f156)
        self.assertEqual(struct2.f157, struct1.f157)

        self.assertEqual(struct2.f1000, struct1.f1000)
        self.assertEqual(struct2.f1001, struct1.f1001)
        self.assertEqual(struct2.f1002, struct1.f1002)
        self.assertEqual(struct2.f1003, struct1.f1003)
        self.assertEqual(struct2.f1004, struct1.f1004)
        self.assertEqual(struct2.f1005, struct1.f1005)
        self.assertEqual(struct2.f1006, struct1.f1006)
        self.assertEqual(struct2.f1007, struct1.f1007)

    def test_serialization_final_struct_bytes(self):
        # Create a new struct
        struct1 = test.StructBytes()
        struct1.f1 = "ABC".encode()
        struct1.f2 = "test".encode()

        # Serialize the struct to the FBE stream
        writer = test.StructBytesFinalModel(fbe.WriteBuffer())
        self.assertEqual(writer.fbe_type, 120)
        serialized = writer.serialize(struct1)
        self.assertEqual(serialized, writer.buffer.size)
        self.assertTrue(writer.verify())
        writer.next(serialized)

        # Check the serialized FBE size
        self.assertEqual(writer.buffer.size, 25)

        # Deserialize the struct from the FBE stream
        struct2 = test.StructBytes()
        reader = test.StructBytesFinalModel(fbe.ReadBuffer())
        self.assertEqual(reader.fbe_type, 120)
        reader.attach_buffer(writer.buffer)
        self.assertTrue(reader.verify())
        (struct2, deserialized) = reader.deserialize(struct2)
        self.assertEqual(deserialized, reader.buffer.size)
        reader.next(deserialized)

        self.assertEqual(len(struct2.f1), 3)
        self.assertEqual(chr(struct2.f1[0]), 'A')
        self.assertEqual(chr(struct2.f1[1]), 'B')
        self.assertEqual(chr(struct2.f1[2]), 'C')
        self.assertNotEqual(struct2.f2, None)
        self.assertEqual(len(struct2.f2), 4)
        self.assertEqual(chr(struct2.f2[0]), 't')
        self.assertEqual(chr(struct2.f2[1]), 'e')
        self.assertEqual(chr(struct2.f2[2]), 's')
        self.assertEqual(chr(struct2.f2[3]), 't')
        self.assertEqual(struct2.f3, None)

    def test_serialization_final_struct_array(self):
        # Create a new struct
        struct1 = test.StructArray()
        struct1.f1[0] = 48
        struct1.f1[1] = 65
        struct1.f2[0] = 97
        struct1.f2[1] = None
        struct1.f3[0] = "000".encode()
        struct1.f3[1] = "AAA".encode()
        struct1.f4[0] = "aaa".encode()
        struct1.f4[1] = None
        struct1.f5[0] = test.EnumSimple.ENUM_VALUE_1
        struct1.f5[1] = test.EnumSimple.ENUM_VALUE_2
        struct1.f6[0] = test.EnumSimple.ENUM_VALUE_1
        struct1.f6[1] = None
        struct1.f7[0] = test.FlagsSimple.FLAG_VALUE_1 | test.FlagsSimple.FLAG_VALUE_2
        struct1.f7[1] = test.FlagsSimple.FLAG_VALUE_1 | test.FlagsSimple.FLAG_VALUE_2 | test.FlagsSimple.FLAG_VALUE_3
        struct1.f8[0] = test.FlagsSimple.FLAG_VALUE_1 | test.FlagsSimple.FLAG_VALUE_2
        struct1.f8[1] = None
        struct1.f9[0] = test.StructSimple()
        struct1.f9[1] = test.StructSimple()
        struct1.f10[0] = test.StructSimple()
        struct1.f10[1] = None

        # Serialize the struct to the FBE stream
        writer = test.StructArrayFinalModel(fbe.WriteBuffer())
        self.assertEqual(writer.fbe_type, 125)
        serialized = writer.serialize(struct1)
        self.assertEqual(serialized, writer.buffer.size)
        self.assertTrue(writer.verify())
        writer.next(serialized)

        # Check the serialized FBE size
        self.assertEqual(writer.buffer.size, 954)

        # Deserialize the struct from the FBE stream
        struct2 = test.StructArray()
        reader = test.StructArrayFinalModel(fbe.ReadBuffer())
        self.assertEqual(reader.fbe_type, 125)
        reader.attach_buffer(writer.buffer)
        self.assertTrue(reader.verify())
        (struct2, deserialized) = reader.deserialize(struct2)
        self.assertEqual(deserialized, reader.buffer.size)
        reader.next(deserialized)

        self.assertEqual(len(struct2.f1), 2)
        self.assertEqual(struct2.f1[0], 48)
        self.assertEqual(struct2.f1[1], 65)
        self.assertEqual(len(struct2.f2), 2)
        self.assertEqual(struct2.f2[0], 97)
        self.assertEqual(struct2.f2[1], None)
        self.assertEqual(len(struct2.f3), 2)
        self.assertEqual(len(struct2.f3[0]), 3)
        self.assertEqual(struct2.f3[0][0], 48)
        self.assertEqual(struct2.f3[0][1], 48)
        self.assertEqual(struct2.f3[0][2], 48)
        self.assertEqual(len(struct2.f3[1]), 3)
        self.assertEqual(struct2.f3[1][0], 65)
        self.assertEqual(struct2.f3[1][1], 65)
        self.assertEqual(struct2.f3[1][2], 65)
        self.assertEqual(len(struct2.f4), 2)
        self.assertNotEqual(struct2.f4[0], None)
        self.assertEqual(len(struct2.f4[0]), 3)
        self.assertEqual(struct2.f4[0][0], 97)
        self.assertEqual(struct2.f4[0][1], 97)
        self.assertEqual(struct2.f4[0][2], 97)
        self.assertEqual(struct2.f4[1], None)
        self.assertEqual(len(struct2.f5), 2)
        self.assertEqual(struct2.f5[0], test.EnumSimple.ENUM_VALUE_1)
        self.assertEqual(struct2.f5[1], test.EnumSimple.ENUM_VALUE_2)
        self.assertEqual(len(struct2.f6), 2)
        self.assertEqual(struct2.f6[0], test.EnumSimple.ENUM_VALUE_1)
        self.assertEqual(struct2.f6[1], None)
        self.assertEqual(len(struct2.f7), 2)
        self.assertEqual(struct2.f7[0], test.FlagsSimple.FLAG_VALUE_1 | test.FlagsSimple.FLAG_VALUE_2)
        self.assertEqual(struct2.f7[1], test.FlagsSimple.FLAG_VALUE_1 | test.FlagsSimple.FLAG_VALUE_2 | test.FlagsSimple.FLAG_VALUE_3)
        self.assertEqual(len(struct2.f8), 2)
        self.assertEqual(struct2.f8[0], test.FlagsSimple.FLAG_VALUE_1 | test.FlagsSimple.FLAG_VALUE_2)
        self.assertEqual(struct2.f8[1], None)
        self.assertEqual(len(struct2.f9), 2)
        self.assertEqual(struct2.f9[0].f2, True)
        self.assertEqual(struct2.f9[0].f12, 0xFF)
        self.assertEqual(struct2.f9[0].f32, "Initial string!")
        self.assertEqual(struct2.f9[1].f2, True)
        self.assertEqual(struct2.f9[1].f12, 0xFF)
        self.assertEqual(struct2.f9[1].f32, "Initial string!")
        self.assertEqual(len(struct2.f10), 2)
        self.assertNotEqual(struct2.f10[0], None)
        self.assertEqual(struct2.f10[0].f2, True)
        self.assertEqual(struct2.f10[0].f12, 0xFF)
        self.assertEqual(struct2.f10[0].f32, "Initial string!")
        self.assertEqual(struct2.f10[1], None)

    def test_serialization_final_struct_vector(self):
        # Create a new struct
        struct1 = test.StructVector()
        struct1.f1.append(48)
        struct1.f1.append(65)
        struct1.f2.append(97)
        struct1.f2.append(None)
        struct1.f3.append("000".encode())
        struct1.f3.append("AAA".encode())
        struct1.f4.append("aaa".encode())
        struct1.f4.append(None)
        struct1.f5.append(test.EnumSimple.ENUM_VALUE_1)
        struct1.f5.append(test.EnumSimple.ENUM_VALUE_2)
        struct1.f6.append(test.EnumSimple.ENUM_VALUE_1)
        struct1.f6.append(None)
        struct1.f7.append(test.FlagsSimple.FLAG_VALUE_1 | test.FlagsSimple.FLAG_VALUE_2)
        struct1.f7.append(test.FlagsSimple.FLAG_VALUE_1 | test.FlagsSimple.FLAG_VALUE_2 | test.FlagsSimple.FLAG_VALUE_3)
        struct1.f8.append(test.FlagsSimple.FLAG_VALUE_1 | test.FlagsSimple.FLAG_VALUE_2)
        struct1.f8.append(None)
        struct1.f9.append(test.StructSimple())
        struct1.f9.append(test.StructSimple())
        struct1.f10.append(test.StructSimple())
        struct1.f10.append(None)

        # Serialize the struct to the FBE stream
        writer = test.StructVectorFinalModel(fbe.WriteBuffer())
        self.assertEqual(writer.fbe_type, 130)
        serialized = writer.serialize(struct1)
        self.assertEqual(serialized, writer.buffer.size)
        self.assertTrue(writer.verify())
        writer.next(serialized)

        # Check the serialized FBE size
        self.assertEqual(writer.buffer.size, 994)

        # Deserialize the struct from the FBE stream
        struct2 = test.StructVector()
        reader = test.StructVectorFinalModel(fbe.ReadBuffer())
        self.assertEqual(reader.fbe_type, 130)
        reader.attach_buffer(writer.buffer)
        self.assertTrue(reader.verify())
        (struct2, deserialized) = reader.deserialize(struct2)
        self.assertEqual(deserialized, reader.buffer.size)
        reader.next(deserialized)

        self.assertEqual(len(struct2.f1), 2)
        self.assertEqual(struct2.f1[0], 48)
        self.assertEqual(struct2.f1[1], 65)
        self.assertEqual(len(struct2.f2), 2)
        self.assertEqual(struct2.f2[0], 97)
        self.assertEqual(struct2.f2[1], None)
        self.assertEqual(len(struct2.f3), 2)
        self.assertEqual(len(struct2.f3[0]), 3)
        self.assertEqual(struct2.f3[0][0], 48)
        self.assertEqual(struct2.f3[0][1], 48)
        self.assertEqual(struct2.f3[0][2], 48)
        self.assertEqual(len(struct2.f3[1]), 3)
        self.assertEqual(struct2.f3[1][0], 65)
        self.assertEqual(struct2.f3[1][1], 65)
        self.assertEqual(struct2.f3[1][2], 65)
        self.assertEqual(len(struct2.f4), 2)
        self.assertNotEqual(struct2.f4[0], None)
        self.assertEqual(len(struct2.f4[0]), 3)
        self.assertEqual(struct2.f4[0][0], 97)
        self.assertEqual(struct2.f4[0][1], 97)
        self.assertEqual(struct2.f4[0][2], 97)
        self.assertEqual(struct2.f4[1], None)
        self.assertEqual(len(struct2.f5), 2)
        self.assertEqual(struct2.f5[0], test.EnumSimple.ENUM_VALUE_1)
        self.assertEqual(struct2.f5[1], test.EnumSimple.ENUM_VALUE_2)
        self.assertEqual(len(struct2.f6), 2)
        self.assertEqual(struct2.f6[0], test.EnumSimple.ENUM_VALUE_1)
        self.assertEqual(struct2.f6[1], None)
        self.assertEqual(len(struct2.f7), 2)
        self.assertEqual(struct2.f7[0], test.FlagsSimple.FLAG_VALUE_1 | test.FlagsSimple.FLAG_VALUE_2)
        self.assertEqual(struct2.f7[1], test.FlagsSimple.FLAG_VALUE_1 | test.FlagsSimple.FLAG_VALUE_2 | test.FlagsSimple.FLAG_VALUE_3)
        self.assertEqual(len(struct2.f8), 2)
        self.assertEqual(struct2.f8[0], test.FlagsSimple.FLAG_VALUE_1 | test.FlagsSimple.FLAG_VALUE_2)
        self.assertEqual(struct2.f8[1], None)
        self.assertEqual(len(struct2.f9), 2)
        self.assertEqual(struct2.f9[0].f2, True)
        self.assertEqual(struct2.f9[0].f12, 0xFF)
        self.assertEqual(struct2.f9[0].f32, "Initial string!")
        self.assertEqual(struct2.f9[1].f2, True)
        self.assertEqual(struct2.f9[1].f12, 0xFF)
        self.assertEqual(struct2.f9[1].f32, "Initial string!")
        self.assertEqual(len(struct2.f10), 2)
        self.assertNotEqual(struct2.f10[0], None)
        self.assertEqual(struct2.f10[0].f2, True)
        self.assertEqual(struct2.f10[0].f12, 0xFF)
        self.assertEqual(struct2.f10[0].f32, "Initial string!")
        self.assertEqual(struct2.f10[1], None)

    def test_serialization_final_struct_list(self):
        # Create a new struct
        struct1 = test.StructList()
        struct1.f1.append(48)
        struct1.f1.append(65)
        struct1.f2.append(97)
        struct1.f2.append(None)
        struct1.f3.append("000".encode())
        struct1.f3.append("AAA".encode())
        struct1.f4.append("aaa".encode())
        struct1.f4.append(None)
        struct1.f5.append(test.EnumSimple.ENUM_VALUE_1)
        struct1.f5.append(test.EnumSimple.ENUM_VALUE_2)
        struct1.f6.append(test.EnumSimple.ENUM_VALUE_1)
        struct1.f6.append(None)
        struct1.f7.append(test.FlagsSimple.FLAG_VALUE_1 | test.FlagsSimple.FLAG_VALUE_2)
        struct1.f7.append(test.FlagsSimple.FLAG_VALUE_1 | test.FlagsSimple.FLAG_VALUE_2 | test.FlagsSimple.FLAG_VALUE_3)
        struct1.f8.append(test.FlagsSimple.FLAG_VALUE_1 | test.FlagsSimple.FLAG_VALUE_2)
        struct1.f8.append(None)
        struct1.f9.append(test.StructSimple())
        struct1.f9.append(test.StructSimple())
        struct1.f10.append(test.StructSimple())
        struct1.f10.append(None)

        # Serialize the struct to the FBE stream
        writer = test.StructListFinalModel(fbe.WriteBuffer())
        self.assertEqual(writer.fbe_type, 131)
        serialized = writer.serialize(struct1)
        self.assertEqual(serialized, writer.buffer.size)
        self.assertTrue(writer.verify())
        writer.next(serialized)

        # Check the serialized FBE size
        self.assertEqual(writer.buffer.size, 994)

        # Deserialize the struct from the FBE stream
        struct2 = test.StructList()
        reader = test.StructListFinalModel(fbe.ReadBuffer())
        self.assertEqual(reader.fbe_type, 131)
        reader.attach_buffer(writer.buffer)
        self.assertTrue(reader.verify())
        (struct2, deserialized) = reader.deserialize(struct2)
        self.assertEqual(deserialized, reader.buffer.size)
        reader.next(deserialized)

        self.assertEqual(len(struct2.f1), 2)
        self.assertEqual(struct2.f1[0], 48)
        self.assertEqual(struct2.f1[1], 65)
        self.assertEqual(len(struct2.f2), 2)
        self.assertEqual(struct2.f2[0], 97)
        self.assertEqual(struct2.f2[1], None)
        self.assertEqual(len(struct2.f3), 2)
        self.assertEqual(len(struct2.f3[0]), 3)
        self.assertEqual(struct2.f3[0][0], 48)
        self.assertEqual(struct2.f3[0][1], 48)
        self.assertEqual(struct2.f3[0][2], 48)
        self.assertEqual(len(struct2.f3[1]), 3)
        self.assertEqual(struct2.f3[1][0], 65)
        self.assertEqual(struct2.f3[1][1], 65)
        self.assertEqual(struct2.f3[1][2], 65)
        self.assertEqual(len(struct2.f4), 2)
        self.assertNotEqual(struct2.f4[0], None)
        self.assertEqual(len(struct2.f4[0]), 3)
        self.assertEqual(struct2.f4[0][0], 97)
        self.assertEqual(struct2.f4[0][1], 97)
        self.assertEqual(struct2.f4[0][2], 97)
        self.assertEqual(struct2.f4[1], None)
        self.assertEqual(len(struct2.f5), 2)
        self.assertEqual(struct2.f5[0], test.EnumSimple.ENUM_VALUE_1)
        self.assertEqual(struct2.f5[1], test.EnumSimple.ENUM_VALUE_2)
        self.assertEqual(len(struct2.f6), 2)
        self.assertEqual(struct2.f6[0], test.EnumSimple.ENUM_VALUE_1)
        self.assertEqual(struct2.f6[1], None)
        self.assertEqual(len(struct2.f7), 2)
        self.assertEqual(struct2.f7[0], test.FlagsSimple.FLAG_VALUE_1 | test.FlagsSimple.FLAG_VALUE_2)
        self.assertEqual(struct2.f7[1], test.FlagsSimple.FLAG_VALUE_1 | test.FlagsSimple.FLAG_VALUE_2 | test.FlagsSimple.FLAG_VALUE_3)
        self.assertEqual(len(struct2.f8), 2)
        self.assertEqual(struct2.f8[0], test.FlagsSimple.FLAG_VALUE_1 | test.FlagsSimple.FLAG_VALUE_2)
        self.assertEqual(struct2.f8[1], None)
        self.assertEqual(len(struct2.f9), 2)
        self.assertEqual(struct2.f9[0].f2, True)
        self.assertEqual(struct2.f9[0].f12, 0xFF)
        self.assertEqual(struct2.f9[0].f32, "Initial string!")
        self.assertEqual(struct2.f9[1].f2, True)
        self.assertEqual(struct2.f9[1].f12, 0xFF)
        self.assertEqual(struct2.f9[1].f32, "Initial string!")
        self.assertEqual(len(struct2.f10), 2)
        self.assertNotEqual(struct2.f10[0], None)
        self.assertEqual(struct2.f10[0].f2, True)
        self.assertEqual(struct2.f10[0].f12, 0xFF)
        self.assertEqual(struct2.f10[0].f32, "Initial string!")
        self.assertEqual(struct2.f10[1], None)

    def test_serialization_final_struct_set(self):
        # Create a new struct
        struct1 = test.StructSet()
        struct1.f1.add(48)
        struct1.f1.add(65)
        struct1.f1.add(97)
        struct1.f2.add(test.EnumSimple.ENUM_VALUE_1)
        struct1.f2.add(test.EnumSimple.ENUM_VALUE_2)
        struct1.f3.add(test.FlagsSimple.FLAG_VALUE_1 | test.FlagsSimple.FLAG_VALUE_2)
        struct1.f3.add(test.FlagsSimple.FLAG_VALUE_1 | test.FlagsSimple.FLAG_VALUE_2 | test.FlagsSimple.FLAG_VALUE_3)
        s1 = test.StructSimple()
        s1.id = 48
        struct1.f4.add(s1)
        s2 = test.StructSimple()
        s2.id = 65
        struct1.f4.add(s2)

        # Serialize the struct to the FBE stream
        writer = test.StructSetFinalModel(fbe.WriteBuffer())
        self.assertEqual(writer.fbe_type, 132)
        serialized = writer.serialize(struct1)
        self.assertEqual(serialized, writer.buffer.size)
        self.assertTrue(writer.verify())
        writer.next(serialized)

        # Check the serialized FBE size
        self.assertEqual(writer.buffer.size, 635)

        # Deserialize the struct from the FBE stream
        struct2 = test.StructSet()
        reader = test.StructSetFinalModel(fbe.ReadBuffer())
        self.assertEqual(reader.fbe_type, 132)
        reader.attach_buffer(writer.buffer)
        self.assertTrue(reader.verify())
        (struct2, deserialized) = reader.deserialize(struct2)
        self.assertEqual(deserialized, reader.buffer.size)
        reader.next(deserialized)

        self.assertEqual(len(struct2.f1), 3)
        self.assertTrue(48 in struct2.f1)
        self.assertTrue(65 in struct2.f1)
        self.assertTrue(97 in struct2.f1)
        self.assertEqual(len(struct2.f2), 2)
        self.assertTrue(test.EnumSimple.ENUM_VALUE_1 in struct2.f2)
        self.assertTrue(test.EnumSimple.ENUM_VALUE_2 in struct2.f2)
        self.assertEqual(len(struct2.f3), 2)
        self.assertTrue((test.FlagsSimple.FLAG_VALUE_1 | test.FlagsSimple.FLAG_VALUE_2) in struct2.f3)
        self.assertTrue((test.FlagsSimple.FLAG_VALUE_1 | test.FlagsSimple.FLAG_VALUE_2 | test.FlagsSimple.FLAG_VALUE_3) in struct2.f3)
        self.assertEqual(len(struct2.f4), 2)
        self.assertTrue(s1 in struct2.f4)
        self.assertTrue(s2 in struct2.f4)

    def test_serialization_final_struct_map(self):
        # Create a new struct
        struct1 = test.StructMap()
        struct1.f1[10] = 48
        struct1.f1[20] = 65
        struct1.f2[10] = 97
        struct1.f2[20] = None
        struct1.f3[10] = "000".encode()
        struct1.f3[20] = "AAA".encode()
        struct1.f4[10] = "aaa".encode()
        struct1.f4[20] = None
        struct1.f5[10] = test.EnumSimple.ENUM_VALUE_1
        struct1.f5[20] = test.EnumSimple.ENUM_VALUE_2
        struct1.f6[10] = test.EnumSimple.ENUM_VALUE_1
        struct1.f6[20] = None
        struct1.f7[10] = test.FlagsSimple.FLAG_VALUE_1 | test.FlagsSimple.FLAG_VALUE_2
        struct1.f7[20] = test.FlagsSimple.FLAG_VALUE_1 | test.FlagsSimple.FLAG_VALUE_2 | test.FlagsSimple.FLAG_VALUE_3
        struct1.f8[10] = test.FlagsSimple.FLAG_VALUE_1 | test.FlagsSimple.FLAG_VALUE_2
        struct1.f8[20] = None
        s1 = test.StructSimple()
        s1.id = 48
        struct1.f9[10] = s1
        s2 = test.StructSimple()
        s2.id = 65
        struct1.f9[20] = s2
        struct1.f10[10] = s1
        struct1.f10[20] = None

        # Serialize the struct to the FBE stream
        writer = test.StructMapFinalModel(fbe.WriteBuffer())
        self.assertEqual(writer.fbe_type, 140)
        serialized = writer.serialize(struct1)
        self.assertEqual(serialized, writer.buffer.size)
        self.assertTrue(writer.verify())
        writer.next(serialized)

        # Check the serialized FBE size
        self.assertEqual(writer.buffer.size, 1074)

        # Deserialize the struct from the FBE stream
        struct2 = test.StructMap()
        reader = test.StructMapFinalModel(fbe.ReadBuffer())
        self.assertEqual(reader.fbe_type, 140)
        reader.attach_buffer(writer.buffer)
        self.assertTrue(reader.verify())
        (struct2, deserialized) = reader.deserialize(struct2)
        self.assertEqual(deserialized, reader.buffer.size)
        reader.next(deserialized)

        self.assertEqual(len(struct2.f1), 2)
        self.assertEqual(struct2.f1[10], 48)
        self.assertEqual(struct2.f1[20], 65)
        self.assertEqual(len(struct2.f2), 2)
        self.assertEqual(struct2.f2[10], 97)
        self.assertEqual(struct2.f2[20], None)
        self.assertEqual(len(struct2.f3), 2)
        self.assertEqual(len(struct2.f3[10]), 3)
        self.assertEqual(len(struct2.f3[20]), 3)
        self.assertEqual(len(struct2.f4), 2)
        self.assertEqual(len(struct2.f4[10]), 3)
        self.assertEqual(struct2.f4[20], None)
        self.assertEqual(len(struct2.f5), 2)
        self.assertEqual(struct2.f5[10], test.EnumSimple.ENUM_VALUE_1)
        self.assertEqual(struct2.f5[20], test.EnumSimple.ENUM_VALUE_2)
        self.assertEqual(len(struct2.f6), 2)
        self.assertEqual(struct2.f6[10], test.EnumSimple.ENUM_VALUE_1)
        self.assertEqual(struct2.f6[20], None)
        self.assertEqual(len(struct2.f7), 2)
        self.assertEqual(struct2.f7[10], test.FlagsSimple.FLAG_VALUE_1 | test.FlagsSimple.FLAG_VALUE_2)
        self.assertEqual(struct2.f7[20], test.FlagsSimple.FLAG_VALUE_1 | test.FlagsSimple.FLAG_VALUE_2 | test.FlagsSimple.FLAG_VALUE_3)
        self.assertEqual(len(struct2.f8), 2)
        self.assertEqual(struct2.f8[10], test.FlagsSimple.FLAG_VALUE_1 | test.FlagsSimple.FLAG_VALUE_2)
        self.assertEqual(struct2.f8[20], None)
        self.assertEqual(len(struct2.f9), 2)
        self.assertEqual(struct2.f9[10].id, 48)
        self.assertEqual(struct2.f9[20].id, 65)
        self.assertEqual(len(struct2.f10), 2)
        self.assertEqual(struct2.f10[10].id, 48)
        self.assertEqual(struct2.f10[20], None)

    def test_serialization_final_struct_hash(self):
        # Create a new struct
        struct1 = test.StructHash()
        struct1.f1["10"] = 48
        struct1.f1["20"] = 65
        struct1.f2["10"] = 97
        struct1.f2["20"] = None
        struct1.f3["10"] = "000".encode()
        struct1.f3["20"] = "AAA".encode()
        struct1.f4["10"] = "aaa".encode()
        struct1.f4["20"] = None
        struct1.f5["10"] = test.EnumSimple.ENUM_VALUE_1
        struct1.f5["20"] = test.EnumSimple.ENUM_VALUE_2
        struct1.f6["10"] = test.EnumSimple.ENUM_VALUE_1
        struct1.f6["20"] = None
        struct1.f7["10"] = test.FlagsSimple.FLAG_VALUE_1 | test.FlagsSimple.FLAG_VALUE_2
        struct1.f7["20"] = test.FlagsSimple.FLAG_VALUE_1 | test.FlagsSimple.FLAG_VALUE_2 | test.FlagsSimple.FLAG_VALUE_3
        struct1.f8["10"] = test.FlagsSimple.FLAG_VALUE_1 | test.FlagsSimple.FLAG_VALUE_2
        struct1.f8["20"] = None
        s1 = test.StructSimple()
        s1.id = 48
        struct1.f9["10"] = s1
        s2 = test.StructSimple()
        s2.id = 65
        struct1.f9["20"] = s2
        struct1.f10["10"] = s1
        struct1.f10["20"] = None

        # Serialize the struct to the FBE stream
        writer = test.StructHashFinalModel(fbe.WriteBuffer())
        self.assertEqual(writer.fbe_type, 141)
        serialized = writer.serialize(struct1)
        self.assertEqual(serialized, writer.buffer.size)
        self.assertTrue(writer.verify())
        writer.next(serialized)

        # Check the serialized FBE size
        self.assertEqual(writer.buffer.size, 1114)

        # Deserialize the struct from the FBE stream
        struct2 = test.StructHash()
        reader = test.StructHashFinalModel(fbe.ReadBuffer())
        self.assertEqual(reader.fbe_type, 141)
        reader.attach_buffer(writer.buffer)
        self.assertTrue(reader.verify())
        (struct2, deserialized) = reader.deserialize(struct2)
        self.assertEqual(deserialized, reader.buffer.size)
        reader.next(deserialized)

        self.assertEqual(len(struct2.f1), 2)
        self.assertEqual(struct2.f1["10"], 48)
        self.assertEqual(struct2.f1["20"], 65)
        self.assertEqual(len(struct2.f2), 2)
        self.assertEqual(struct2.f2["10"], 97)
        self.assertEqual(struct2.f2["20"], None)
        self.assertEqual(len(struct2.f3), 2)
        self.assertEqual(len(struct2.f3["10"]), 3)
        self.assertEqual(len(struct2.f3["20"]), 3)
        self.assertEqual(len(struct2.f4), 2)
        self.assertEqual(len(struct2.f4["10"]), 3)
        self.assertEqual(struct2.f4["20"], None)
        self.assertEqual(len(struct2.f5), 2)
        self.assertEqual(struct2.f5["10"], test.EnumSimple.ENUM_VALUE_1)
        self.assertEqual(struct2.f5["20"], test.EnumSimple.ENUM_VALUE_2)
        self.assertEqual(len(struct2.f6), 2)
        self.assertEqual(struct2.f6["10"], test.EnumSimple.ENUM_VALUE_1)
        self.assertEqual(struct2.f6["20"], None)
        self.assertEqual(len(struct2.f7), 2)
        self.assertEqual(struct2.f7["10"], test.FlagsSimple.FLAG_VALUE_1 | test.FlagsSimple.FLAG_VALUE_2)
        self.assertEqual(struct2.f7["20"], test.FlagsSimple.FLAG_VALUE_1 | test.FlagsSimple.FLAG_VALUE_2 | test.FlagsSimple.FLAG_VALUE_3)
        self.assertEqual(len(struct2.f8), 2)
        self.assertEqual(struct2.f8["10"], test.FlagsSimple.FLAG_VALUE_1 | test.FlagsSimple.FLAG_VALUE_2)
        self.assertEqual(struct2.f8["20"], None)
        self.assertEqual(len(struct2.f9), 2)
        self.assertEqual(struct2.f9["10"].id, 48)
        self.assertEqual(struct2.f9["20"].id, 65)
        self.assertEqual(len(struct2.f10), 2)
        self.assertEqual(struct2.f10["10"].id, 48)
        self.assertEqual(struct2.f10["20"], None)

    def test_serialization_final_struct_hash_extended(self):
        # Create a new struct
        struct1 = test.StructHashEx()
        s1 = test.StructSimple()
        s1.id = 48
        struct1.f1[s1] = test.StructNested()
        s2 = test.StructSimple()
        s2.id = 65
        struct1.f1[s2] = test.StructNested()
        struct1.f2[s1] = test.StructNested()
        struct1.f2[s2] = None

        # Serialize the struct to the FBE stream
        writer = test.StructHashExFinalModel(fbe.WriteBuffer())
        self.assertEqual(writer.fbe_type, 142)
        serialized = writer.serialize(struct1)
        self.assertEqual(serialized, writer.buffer.size)
        self.assertTrue(writer.verify())
        writer.next(serialized)

        # Check the serialized FBE size
        self.assertEqual(writer.buffer.size, 4979)

        # Deserialize the struct from the FBE stream
        struct2 = test.StructHashEx()
        reader = test.StructHashExFinalModel(fbe.ReadBuffer())
        self.assertEqual(reader.fbe_type, 142)
        reader.attach_buffer(writer.buffer)
        self.assertTrue(reader.verify())
        (struct2, deserialized) = reader.deserialize(struct2)
        self.assertEqual(deserialized, reader.buffer.size)
        reader.next(deserialized)

        self.assertEqual(len(struct2.f1), 2)
        self.assertEqual(struct2.f1[s1].f1002, test.EnumTyped.ENUM_VALUE_2)
        self.assertEqual(struct2.f1[s2].f1002, test.EnumTyped.ENUM_VALUE_2)
        self.assertEqual(len(struct2.f2), 2)
        self.assertEqual(struct2.f2[s1].f1002, test.EnumTyped.ENUM_VALUE_2)
        self.assertEqual(struct2.f2[s2], None)
