public async Task CanUseEncoderWithServiceBusMessageUsingFunc()
        {
            var client    = CreateClient();
            var groupName = TestEnvironment.SchemaRegistryGroup;

            var encoder = new SchemaRegistryAvroEncoder(client, groupName, new SchemaRegistryAvroObjectEncoderOptions {
                AutoRegisterSchemas = true
            });

            var employee = new Employee {
                Age = 42, Name = "Caketown"
            };
            ServiceBusMessage message = await encoder.EncodeMessageDataAsync(employee, messageFactory : bd => new ServiceBusMessage(bd));

            string[] contentType = message.ContentType.Split('+');
            Assert.AreEqual(2, contentType.Length);
            Assert.AreEqual("avro/binary", contentType[0]);
            Assert.IsNotEmpty(contentType[1]);

            ServiceBusReceivedMessage receivedMessage =
                ServiceBusModelFactory.ServiceBusReceivedMessage(body: message.Body, contentType: message.ContentType);

            Employee deserialized = await encoder.DecodeMessageDataAsync <Employee>(receivedMessage);

            // decoding should not alter the message
            contentType = message.ContentType.Split('+');
            Assert.AreEqual(2, contentType.Length);
            Assert.AreEqual("avro/binary", contentType[0]);
            Assert.IsNotEmpty(contentType[1]);

            // verify the payload was decoded correctly
            Assert.IsNotNull(deserialized);
            Assert.AreEqual("Caketown", deserialized.Name);
            Assert.AreEqual(42, deserialized.Age);
        }
        public async Task CanSerializeAndDeserializeWithCompatibleSchema()
        {
            var client    = CreateClient();
            var groupName = TestEnvironment.SchemaRegistryGroup;
            var employee  = new Employee_V2 {
                Age = 42, Name = "Caketown", City = "Redmond"
            };

            var encoder = new SchemaRegistryAvroEncoder(client, groupName, new SchemaRegistryAvroObjectEncoderOptions()
            {
                AutoRegisterSchemas = true
            });
            var messageData = await encoder.EncodeMessageDataAsync <MessageWithMetadata>(employee, typeof(Employee_V2));

            // deserialize using the old schema, which is forward compatible with the new schema
            // if you swap the old schema and the new schema in your mind, then this can also be thought as a backwards compatible test
            var deserializedObject = await encoder.DecodeMessageDataAsync <Employee>(messageData);

            var readEmployee = deserializedObject as Employee;

            Assert.IsNotNull(readEmployee);
            Assert.AreEqual("Caketown", readEmployee.Name);
            Assert.AreEqual(42, readEmployee.Age);

            // deserialize using the new schema to make sure we are respecting it
            var readEmployeeV2 = await encoder.DecodeMessageDataAsync <Employee_V2>(messageData);

            Assert.IsNotNull(readEmployee);
            Assert.AreEqual("Caketown", readEmployeeV2.Name);
            Assert.AreEqual(42, readEmployeeV2.Age);
            Assert.AreEqual("Redmond", readEmployeeV2.City);
        }
        public async Task CannotSerializeUnsupportedType()
        {
            var client       = CreateClient();
            var groupName    = TestEnvironment.SchemaRegistryGroup;
            var timeZoneInfo = TimeZoneInfo.Utc;

            var encoder = new SchemaRegistryAvroEncoder(client, groupName, new SchemaRegistryAvroObjectEncoderOptions {
                AutoRegisterSchemas = true
            });

            Assert.ThrowsAsync <ArgumentException>(async() => await encoder.EncodeMessageDataAsync <MessageWithMetadata>(timeZoneInfo, typeof(TimeZoneInfo)));
            await Task.CompletedTask;
        }
        public async Task CanUseEncoderWithEventData()
        {
            var client    = CreateClient();
            var groupName = TestEnvironment.SchemaRegistryGroup;

            #region Snippet:SchemaRegistryAvroEncodeEventData
            var encoder = new SchemaRegistryAvroEncoder(client, groupName, new SchemaRegistryAvroObjectEncoderOptions {
                AutoRegisterSchemas = true
            });

            var employee = new Employee {
                Age = 42, Name = "Caketown"
            };
            EventData eventData = await encoder.EncodeMessageDataAsync <EventData>(employee);

#if SNIPPET
            // the schema Id will be included as a parameter of the content type
            Console.WriteLine(eventData.ContentType);

            // the serialized Avro data will be stored in the EventBody
            Console.WriteLine(eventData.EventBody);
#endif
            #endregion

            Assert.IsFalse(((MessageWithMetadata)eventData).IsReadOnly);
            string[] contentType = eventData.ContentType.Split('+');
            Assert.AreEqual(2, contentType.Length);
            Assert.AreEqual("avro/binary", contentType[0]);
            Assert.IsNotEmpty(contentType[1]);

            #region Snippet:SchemaRegistryAvroDecodeEventData
            Employee deserialized = await encoder.DecodeMessageDataAsync <Employee>(eventData);

#if SNIPPET
            Console.WriteLine(deserialized.Age);
            Console.WriteLine(deserialized.Name);
#endif
            #endregion

            // decoding should not alter the message
            contentType = eventData.ContentType.Split('+');
            Assert.AreEqual(2, contentType.Length);
            Assert.AreEqual("avro/binary", contentType[0]);
            Assert.IsNotEmpty(contentType[1]);

            // verify the payload was decoded correctly
            Assert.IsNotNull(deserialized);
            Assert.AreEqual("Caketown", deserialized.Name);
            Assert.AreEqual(42, deserialized.Age);
        }
        public async Task CanSerializeAndDeserializeGenericRecord()
        {
            var client    = CreateClient();
            var groupName = TestEnvironment.SchemaRegistryGroup;
            var record    = new GenericRecord((RecordSchema)Employee._SCHEMA);

            record.Add("Name", "Caketown");
            record.Add("Age", 42);

            var encoder = new SchemaRegistryAvroEncoder(client, groupName, new SchemaRegistryAvroObjectEncoderOptions {
                AutoRegisterSchemas = true
            });
            var messageData = await encoder.EncodeMessageDataAsync <MessageWithMetadata>(record, typeof(GenericRecord));

            var deserializedObject = await encoder.DecodeMessageDataAsync <GenericRecord>(messageData);

            var readRecord = deserializedObject as GenericRecord;

            Assert.IsNotNull(readRecord);
            Assert.AreEqual("Caketown", readRecord.GetValue(0));
            Assert.AreEqual(42, readRecord.GetValue(1));
        }
        public async Task CanSerializeAndDeserialize()
        {
            var client    = CreateClient();
            var groupName = TestEnvironment.SchemaRegistryGroup;
            var employee  = new Employee {
                Age = 42, Name = "Caketown"
            };

            #region Snippet:SchemaRegistryAvroEncodeDecodeMessageWithMetadata
            var encoder = new SchemaRegistryAvroEncoder(client, groupName, new SchemaRegistryAvroObjectEncoderOptions()
            {
                AutoRegisterSchemas = true
            });
            MessageWithMetadata messageData = await encoder.EncodeMessageDataAsync <MessageWithMetadata>(employee, typeof(Employee));

            Employee decodedEmployee = await encoder.DecodeMessageDataAsync <Employee>(messageData);

            #endregion

            Assert.IsNotNull(decodedEmployee);
            Assert.AreEqual("Caketown", decodedEmployee.Name);
            Assert.AreEqual(42, decodedEmployee.Age);
        }
        public async Task CanDecodePreamble()
        {
            var client    = CreateClient();
            var groupName = TestEnvironment.SchemaRegistryGroup;

            var encoder = new SchemaRegistryAvroEncoder(client, groupName, new SchemaRegistryAvroObjectEncoderOptions {
                AutoRegisterSchemas = true
            });

            var employee = new Employee {
                Age = 42, Name = "Caketown"
            };
            EventData eventData = await encoder.EncodeMessageDataAsync <EventData>(employee);

            string schemaId = eventData.ContentType.Split('+')[1];

            eventData.ContentType = "avro/binary";

            using var stream = new MemoryStream();
            stream.Write(new byte[] { 0, 0, 0, 0 }, 0, 4);
            var encoding = new UTF8Encoding(false);

            stream.Write(encoding.GetBytes(schemaId), 0, 32);
            stream.Write(eventData.Body.ToArray(), 0, eventData.Body.Length);
            stream.Position     = 0;
            eventData.EventBody = BinaryData.FromStream(stream);

            Employee deserialized = await encoder.DecodeMessageDataAsync <Employee>(eventData);

            // decoding should not alter the message
            Assert.AreEqual("avro/binary", eventData.ContentType);

            // verify the payload was decoded correctly
            Assert.IsNotNull(deserialized);
            Assert.AreEqual("Caketown", deserialized.Name);
            Assert.AreEqual(42, deserialized.Age);
        }