public void CreateEventFromMessagePopulatesSystemProperties()
        {
            var offset         = 123;
            var sequenceNumber = (Int64.MaxValue - 10);
            var enqueuedTime   = DateTimeOffset.Parse("2015-10-27T12:00:00Z");
            var partitionKey   = "OMG! partition!";

            using var bodyStream = new MemoryStream(new byte[] { 0x11, 0x22, 0x33 }, false);
            using var message    = AmqpMessage.Create(bodyStream, true);

            message.ApplicationProperties.Map.Add("First", 1);
            message.ApplicationProperties.Map.Add("Second", "2");

            message.MessageAnnotations.Map.Add(AmqpProperty.Offset, offset.ToString());
            message.MessageAnnotations.Map.Add(AmqpProperty.SequenceNumber, sequenceNumber);
            message.MessageAnnotations.Map.Add(AmqpProperty.EnqueuedTime, new DescribedType(AmqpProperty.Descriptor.DateTimeOffset, enqueuedTime.Ticks));
            message.MessageAnnotations.Map.Add(AmqpProperty.PartitionKey, partitionKey);

            var converter = new AmqpMessageConverter();
            var eventData = converter.CreateEventFromMessage(message);

            Assert.That(eventData, Is.Not.Null, "The event should have been created.");
            Assert.That(eventData.Body, Is.Not.Null, "The event should have a body.");
            Assert.That(eventData.Properties.Count, Is.EqualTo(message.ApplicationProperties.Map.Count()), "The event should have a set of properties.");
            Assert.That(eventData.Offset, Is.EqualTo(offset), "The offset should match.");
            Assert.That(eventData.SequenceNumber, Is.EqualTo(sequenceNumber), "The sequence number should match.");
            Assert.That(eventData.EnqueuedTime, Is.EqualTo(enqueuedTime), "The enqueue time should match.");
            Assert.That(eventData.PartitionKey, Is.EqualTo(partitionKey), "The partition key should match.");
        }
        public void CreateEventFromMessagePopulatesSimpleApplicationProperties()
        {
            var propertyValues = new object[]
            {
                (byte)0x22,
                (sbyte)0x11,
                (Int16)5,
                (Int32)27,
                (Int64)1122334,
                (UInt16)12,
                (UInt32)24,
                (UInt64)9955,
                (Single)4.3,
                (Double)3.4,
                (Decimal)7.893,
                Guid.NewGuid(),
                DateTime.Parse("2015-10-27T12:00:00Z"),
                true,
                'x',
                "hello"
            };

            var applicationProperties = propertyValues.ToDictionary(value => $"{ value.GetType().Name }Property", value => value);

            using var bodyStream = new MemoryStream(new byte[] { 0x11, 0x22, 0x33 }, false);
            using var message    = AmqpMessage.Create(bodyStream, true);

            foreach (var pair in applicationProperties)
            {
                message.ApplicationProperties.Map.Add(pair.Key, pair.Value);
            }

            var converter = new AmqpMessageConverter();
            var eventData = converter.CreateEventFromMessage(message);

            Assert.That(eventData, Is.Not.Null, "The event should have been created.");
            Assert.That(eventData.Body, Is.Not.Null, "The event should have a body.");
            Assert.That(eventData.Properties.Any(), Is.True, "The event should have a set of application properties.");

            // The collection comparisons built into the test assertions do not recognize
            // the property sets as equivalent, but a manual inspection proves the properties exist
            // in both.

            foreach (var property in applicationProperties.Keys)
            {
                var containsValue = eventData.Properties.TryGetValue(property, out object value);

                Assert.That(containsValue, Is.True, $"The event properties did not contain: [{ property }]");
                Assert.That(value, Is.EqualTo(applicationProperties[property]), $"The property value did not match for: [{ property }]");
            }
        }
        public void CreateEventFromMessagePopulatesTheBody()
        {
            var body = new byte[] { 0x11, 0x22, 0x33 };

            using var bodyStream = new MemoryStream(body, false);
            using var message    = AmqpMessage.Create(bodyStream, true);

            var converter = new AmqpMessageConverter();
            var eventData = converter.CreateEventFromMessage(message);

            Assert.That(eventData, Is.Not.Null, "The event should have been created.");
            Assert.That(eventData.Body, Is.Not.Null, "The event should have a body.");
            Assert.That(eventData.Body.ToArray(), Is.EqualTo(body), "The body contents should match.");
        }
        public void AnEventCanBeTranslatedToItself()
        {
            var sourceEvent = new EventData(new byte[] { 0x11, 0x22, 0x33 })
            {
                Properties = new Dictionary <string, object> {
                    { "Test", 1234 }
                }
            };

            var converter = new AmqpMessageConverter();

            using var message = converter.CreateMessageFromEvent(sourceEvent);
            var eventData = converter.CreateEventFromMessage(message);

            Assert.That(message, Is.Not.Null, "The AMQP message should have been created.");
            Assert.That(eventData, Is.Not.Null, "The translated event should have been created.");
            Assert.That(eventData.IsEquivalentTo(sourceEvent), "The translated event should match the source event.");
        }
        public void  CreateEventFromMessageDoesNotIncludeUnknownApplicationPropertyType()
        {
            using var bodyStream = new MemoryStream(new byte[] { 0x11, 0x22, 0x33 }, false);
            using var message    = AmqpMessage.Create(bodyStream, true);

            var typeDescriptor    = (AmqpSymbol)"INVALID";
            var describedProperty = new DescribedType(typeDescriptor, 1234);

            message.ApplicationProperties.Map.Add(typeDescriptor.ToString(), describedProperty);

            var converter = new AmqpMessageConverter();
            var eventData = converter.CreateEventFromMessage(message);

            Assert.That(eventData, Is.Not.Null, "The event should have been created.");
            Assert.That(eventData.Body, Is.Not.Null, "The event should have a body.");
            Assert.That(eventData.Properties.Any(), Is.False, "The event should not have a set of application properties.");

            var containsValue = eventData.Properties.TryGetValue(typeDescriptor.ToString(), out var _);

            Assert.That(containsValue, Is.False, $"The event properties should not contain the described property.");
        }
        public void  CreateEventFromMessagePopulatesAnArraySegmentApplicationPropertyType()
        {
            using var bodyStream = new MemoryStream(new byte[] { 0x11, 0x22, 0x33 }, false);
            using var message    = AmqpMessage.Create(bodyStream, true);

            var propertyKey   = "Test";
            var propertyValue = new byte[] { 0x11, 0x15, 0xF8, 0x20 };

            message.ApplicationProperties.Map.Add(propertyKey, new ArraySegment <byte>(propertyValue, 1, 2));

            var converter = new AmqpMessageConverter();
            var eventData = converter.CreateEventFromMessage(message);

            Assert.That(eventData, Is.Not.Null, "The event should have been created.");
            Assert.That(eventData.Body, Is.Not.Null, "The event should have a body.");
            Assert.That(eventData.Properties.Any(), Is.True, "The event should have a set of application properties.");

            var containsValue = eventData.Properties.TryGetValue(propertyKey, out var eventValue);

            Assert.That(containsValue, Is.True, $"The event properties should contain the property.");
            Assert.That(eventValue, Is.EquivalentTo(propertyValue.Skip(1).Take(2)));
        }
        public void CreateEventFromMessagePopulateDescribedApplicationProperties(object typeDescriptor,
                                                                                 object propertyValueRaw,
                                                                                 Func <object, object> propertyValueAccessor)
        {
            using var bodyStream = new MemoryStream(new byte[] { 0x11, 0x22, 0x33 }, false);
            using var message    = AmqpMessage.Create(bodyStream, true);

            var describedProperty = new DescribedType(typeDescriptor, propertyValueAccessor(propertyValueRaw));

            message.ApplicationProperties.Map.Add(typeDescriptor.ToString(), describedProperty);

            var converter = new AmqpMessageConverter();
            var eventData = converter.CreateEventFromMessage(message);

            Assert.That(eventData, Is.Not.Null, "The event should have been created.");
            Assert.That(eventData.Body, Is.Not.Null, "The event should have a body.");
            Assert.That(eventData.Properties.Any(), Is.True, "The event should have a set of application properties.");

            var containsValue = eventData.Properties.TryGetValue(typeDescriptor.ToString(), out object value);

            Assert.That(containsValue, Is.True, $"The event properties did not contain the described property.");
            Assert.That(value, Is.EqualTo(propertyValueRaw), $"The property value did not match.");
        }
        public void CreateEventFromMessageValidatesTheSource()
        {
            var converter = new AmqpMessageConverter();

            Assert.That(() => converter.CreateEventFromMessage(null), Throws.ArgumentNullException);
        }