public void TryAddDoesNotAcceptAnEventBiggerThanTheMaximumSize() { var maximumSize = 50; var batchEnvelopeSize = 0; var options = new CreateBatchOptions { MaximumSizeInBytes = maximumSize }; var mockEnvelope = new Mock <AmqpMessage>(); var mockEvent = new Mock <AmqpMessage>(); var mockConverter = new InjectableMockConverter { CreateBatchFromEventsHandler = (_e, _p) => mockEnvelope.Object, CreateMessageFromEventHandler = (_e, _p) => mockEvent.Object }; mockEnvelope .Setup(message => message.SerializedMessageSize) .Returns(batchEnvelopeSize); mockEvent .Setup(message => message.SerializedMessageSize) .Returns(maximumSize); var batch = new AmqpEventBatch(mockConverter, options, default); Assert.That(batch.TryAdd(new EventData(new byte[0])), Is.False, "An event of the maximum size is too large due to the reserved overhead."); }
public void SequenceBatchRollsOverSequenceNumbersToZero() { var options = new CreateBatchOptions { MaximumSizeInBytes = 5000 }; var mockEnvelope = new Mock <AmqpMessage>(); var mockConverter = new InjectableMockConverter { CreateBatchFromMessagesHandler = (_e, _p) => mockEnvelope.Object, CreateMessageFromEventHandler = (_e, _p) => AmqpMessage.Create(new FramingData { Value = new ArraySegment <byte>(new byte[] { 0x66 }) }) }; mockEnvelope .Setup(message => message.SerializedMessageSize) .Returns(0); // Add the messages to the batch; all should be accepted. var batch = new AmqpEventBatch(mockConverter, options, default); Assert.That(batch.TryAdd(new EventData(new byte[0])), Is.True, "The event should be accepted into the batch."); // Sequence the batch and validate the final state. var lastSequence = batch.ApplyBatchSequencing(int.MaxValue, null, null); Assert.That(lastSequence, Is.EqualTo(0), "The sequence number should wrap around to 0."); }
public void TryAddAcceptsAnEventSmallerThanTheMaximumSize() { var maximumSize = 50; var eventMessageSize = 40; var options = new CreateBatchOptions { MaximumSizeInBytes = maximumSize }; var mockEnvelope = new Mock <AmqpMessage>(); var mockEvent = new Mock <AmqpMessage>(); var mockConverter = new InjectableMockConverter { CreateBatchFromEventsHandler = (_e, _p) => mockEnvelope.Object, CreateMessageFromEventHandler = (_e, _p) => mockEvent.Object }; mockEnvelope .Setup(message => message.SerializedMessageSize) .Returns(0); mockEvent .Setup(message => message.SerializedMessageSize) .Returns(eventMessageSize); var batch = new AmqpEventBatch(mockConverter, options, default); Assert.That(batch.TryAdd(new EventData(new byte[0])), Is.True); }
public void TryAddSetsTheCount() { var currentIndex = -1; var options = new BatchOptions { MaximumizeInBytes = 5000 }; var eventMessages = new AmqpMessage[5]; var mockEnvelope = new Mock <AmqpMessage>(); var mockConverter = new InjectableMockConverter(); mockConverter.CreateBatchFromEventsHandler = (_e, _p) => mockEnvelope.Object; mockConverter.CreateMessageFromEventHandler = (_e, _p) => eventMessages[++currentIndex]; mockEnvelope .Setup(message => message.SerializedMessageSize) .Returns(0); for (var index = 0; index < eventMessages.Length; ++index) { eventMessages[index] = AmqpMessage.Create(new Data { Value = new ArraySegment <byte>(new byte[] { 0x66 }) }); } // Add the messages to the batch; all should be accepted. var batch = new AmqpEventBatch(mockConverter, options); for (var index = 0; index < eventMessages.Length; ++index) { Assert.That(batch.TryAdd(new EventData(new byte[0])), Is.True, $"The addition for index: { index } should fit and be accepted."); } Assert.That(batch.Count, Is.EqualTo(eventMessages.Length), "The count should have been set when the batch was updated."); }
public void ConstructorValidatesTheOptions() { var mockConverter = new InjectableMockConverter { CreateBatchFromEventsHandler = (_e, _p) => Mock.Of <AmqpMessage>() }; Assert.That(() => new AmqpEventBatch(mockConverter, null, default), Throws.ArgumentNullException); }
public void ConstructorValidatesTheMaximumSize() { var mockConverter = new InjectableMockConverter { CreateBatchFromEventsHandler = (_e, _p) => Mock.Of <AmqpMessage>() }; Assert.That(() => new AmqpEventBatch(mockConverter, new CreateBatchOptions { MaximumSizeInBytes = null }), Throws.ArgumentNullException); }
public void SequenceBatchAppliesPublishingProperties() { var expectedGroupId = 123; var expectedOwnerLevel = (short)6; var firstSequence = 0; var sequenceIndex = -1; var currentIndex = -1; var options = new CreateBatchOptions { MaximumSizeInBytes = 5000 }; var eventMessages = new AmqpMessage[5]; var mockEnvelope = new Mock <AmqpMessage>(); var mockConverter = new InjectableMockConverter { CreateBatchFromMessagesHandler = (_e, _p) => mockEnvelope.Object, CreateMessageFromEventHandler = (_e, _p) => eventMessages[++currentIndex], ApplyPublisherPropertiesToAmqpMessageHandler = (message, sequence, group, owner) => { ++sequenceIndex; Assert.That(sequence, Is.GreaterThan(firstSequence), $"The sequence number for index: { sequenceIndex } should be greater than the initial sequence number."); Assert.That(group, Is.EqualTo(expectedGroupId), $"The group for index: { sequenceIndex } should match."); Assert.That(owner, Is.EqualTo(expectedOwnerLevel), $"The owner for index: { sequenceIndex } should match."); } }; mockEnvelope .Setup(message => message.SerializedMessageSize) .Returns(0); for (var index = 0; index < eventMessages.Length; ++index) { eventMessages[index] = AmqpMessage.Create(new FramingData { Value = new ArraySegment <byte>(new byte[] { 0x66 }) }); } // Add the messages to the batch; all should be accepted. var batch = new AmqpEventBatch(mockConverter, options, default); for (var index = 0; index < eventMessages.Length; ++index) { Assert.That(batch.TryAdd(new EventData(new byte[0])), Is.True, $"The addition for index: { index } should fit and be accepted."); } // Sequence the batch and validate the final state. var lastSequence = batch.ApplyBatchSequencing(firstSequence, expectedGroupId, expectedOwnerLevel); Assert.That(lastSequence, Is.EqualTo(firstSequence + eventMessages.Length), "The final sequence number should indicate a 1-by-1 advancement."); }
public void TryAddValidatesTheEvent() { var mockConverter = new InjectableMockConverter { CreateBatchFromEventsHandler = (_e, _p) => Mock.Of <AmqpMessage>() }; var batch = new AmqpEventBatch(mockConverter, new CreateBatchOptions { MaximumSizeInBytes = 25 }, default); Assert.That(() => batch.TryAdd(null), Throws.ArgumentNullException); }
public void DisposeCleansUpBatchMessages() { var currentIndex = -1; var options = new CreateBatchOptions { MaximumSizeInBytes = 5000 }; var eventMessages = new AmqpMessage[5]; var mockEnvelope = new Mock <AmqpMessage>(); var mockConverter = new InjectableMockConverter { CreateBatchFromMessagesHandler = (_e, _p) => mockEnvelope.Object, CreateMessageFromEventHandler = (_e, _p) => eventMessages[++currentIndex] }; mockEnvelope .Setup(message => message.SerializedMessageSize) .Returns(0); for (var index = 0; index < eventMessages.Length; ++index) { eventMessages[index] = AmqpMessage.Create(new FramingData { Value = new ArraySegment <byte>(new byte[] { 0x66 }) }); } // Add the messages to the batch; all should be accepted. var batch = new AmqpEventBatch(mockConverter, options, default); for (var index = 0; index < eventMessages.Length; ++index) { Assert.That(batch.TryAdd(new EventData(new byte[0])), Is.True, $"The addition for index: { index } should fit and be accepted."); } // Validate that the AMQP messages have not been disposed. for (var index = 0; index < eventMessages.Length; ++index) { Assert.That(() => eventMessages[index].ThrowIfDisposed(), Throws.Nothing, $"The message at index: { index } should not have been disposed."); } // Dispose the batch and verify that the messages held by the batch have been disposed. batch.Dispose(); for (var index = 0; index < eventMessages.Length; ++index) { Assert.That(() => eventMessages[index].ThrowIfDisposed(), Throws.InstanceOf <ObjectDisposedException>(), $"The message at index: { index } should have been disposed."); } }
public void TryAddValidatesNotDisposed() { var mockConverter = new InjectableMockConverter { CreateBatchFromEventsHandler = (_e, _p) => Mock.Of <AmqpMessage>() }; var batch = new AmqpEventBatch(mockConverter, new CreateBatchOptions { MaximumSizeInBytes = 25 }, default); batch.Dispose(); Assert.That(() => batch.TryAdd(new EventData(new byte[0])), Throws.InstanceOf <ObjectDisposedException>()); }
public void AsEnumerableReturnsTheEvents() { var currentIndex = -1; var maximumSize = 5000; var options = new CreateBatchOptions { MaximumSizeInBytes = maximumSize }; var eventMessages = new AmqpMessage[5]; var batchEvents = new EventData[5]; var mockEnvelope = new Mock <AmqpMessage>(); var mockConverter = new InjectableMockConverter { CreateBatchFromEventsHandler = (_e, _p) => mockEnvelope.Object, CreateMessageFromEventHandler = (_e, _p) => eventMessages[++currentIndex] }; mockEnvelope .Setup(message => message.SerializedMessageSize) .Returns(0); for (var index = 0; index < eventMessages.Length; ++index) { var message = new Mock <AmqpMessage>(); message.Setup(msg => msg.SerializedMessageSize).Returns(50); eventMessages[index] = message.Object; } var batch = new AmqpEventBatch(mockConverter, options, default); for (var index = 0; index < eventMessages.Length; ++index) { batchEvents[index] = new EventData(new byte[0]); batch.TryAdd(batchEvents[index]); } IEnumerable <EventData> batchEnumerable = batch.AsEnumerable <EventData>(); Assert.That(batchEnumerable, Is.Not.Null, "The batch enumerable should have been populated."); var batchEnumerableList = batchEnumerable.ToList(); Assert.That(batchEnumerableList.Count, Is.EqualTo(batch.Count), "The wrong number of events was in the enumerable."); for (var index = 0; index < batchEvents.Length; ++index) { Assert.That(batchEnumerableList.Contains(batchEvents[index]), $"The event at index: { index } was not in the enumerable."); } }
public void ConstructorSetsTheMaximumSize() { var maximumSize = 9943; var options = new CreateBatchOptions { MaximumSizeInBytes = maximumSize }; var mockConverter = new InjectableMockConverter { CreateBatchFromEventsHandler = (_e, _p) => Mock.Of <AmqpMessage>() }; var batch = new AmqpEventBatch(mockConverter, options, default); Assert.That(batch.MaximumSizeInBytes, Is.EqualTo(maximumSize)); }
public void TryAddAcceptEventsUntilTheMaximumSizeIsReached() { var currentIndex = -1; var maximumSize = 50; var options = new CreateBatchOptions { MaximumSizeInBytes = maximumSize }; var eventMessages = new AmqpMessage[5]; var mockEnvelope = new Mock <AmqpMessage>(); var mockConverter = new InjectableMockConverter { CreateBatchFromEventsHandler = (_e, _p) => mockEnvelope.Object, CreateMessageFromEventHandler = (_e, _p) => eventMessages[++currentIndex] }; mockEnvelope .Setup(message => message.SerializedMessageSize) .Returns(0); // Fill the set of messages with ones that should fit, reserving the last spot // for one that will deterministically be rejected. for (var index = 0; index < eventMessages.Length; ++index) { var size = (index == eventMessages.Length - 1) ? maximumSize : (maximumSize / eventMessages.Length) - 8; var message = new Mock <AmqpMessage>(); message.Setup(msg => msg.SerializedMessageSize).Returns(size); eventMessages[index] = message.Object; } var batch = new AmqpEventBatch(mockConverter, options, default); for (var index = 0; index < eventMessages.Length; ++index) { if (index == eventMessages.Length - 1) { Assert.That(batch.TryAdd(new EventData(new byte[0])), Is.False, "The final addition should not fit in the available space."); } else { Assert.That(batch.TryAdd(new EventData(new byte[0])), Is.True, $"The addition for index: { index } should fit and be accepted."); } } }
public void TryAddHonorStatefulFeatures(byte activeFeatures) { var maximumSize = 50; var batchEnvelopeSize = 0; var capturedSequence = default(int?); var capturedGroupId = default(long?); var capturedOwnerLevel = default(short?); var options = new CreateBatchOptions { MaximumSizeInBytes = maximumSize }; var mockEnvelope = new Mock <AmqpMessage>(); var mockEvent = new Mock <AmqpMessage>(); var mockConverter = new InjectableMockConverter { CreateBatchFromEventsHandler = (_e, _p) => mockEnvelope.Object, CreateMessageFromEventHandler = (_e, _p) => { capturedSequence = _e.PendingPublishSequenceNumber; capturedGroupId = _e.PendingProducerGroupId; capturedOwnerLevel = _e.PendingProducerOwnerLevel; return(mockEvent.Object); } }; mockEnvelope .Setup(message => message.SerializedMessageSize) .Returns(batchEnvelopeSize); mockEvent .Setup(message => message.SerializedMessageSize) .Returns(maximumSize); var batch = new AmqpEventBatch(mockConverter, options, (TransportProducerFeatures)activeFeatures); batch.TryAdd(EventGenerator.CreateEvents(1).Single()); NullConstraint generateConstraint() => ((TransportProducerFeatures)activeFeatures == TransportProducerFeatures.None) ? Is.Null : Is.Not.Null; Assert.That(capturedSequence, generateConstraint(), "The sequence was not set as expected."); Assert.That(capturedGroupId, generateConstraint(), "The group identifier was not set as expected."); Assert.That(capturedOwnerLevel, generateConstraint(), "The owner level was not set as expected."); }
public void AsEnumerableValidatesTheTypeParameter() { var options = new BatchOptions { MaximumizeInBytes = 5000 }; var mockEnvelope = new Mock <AmqpMessage>(); var mockConverter = new InjectableMockConverter(); mockConverter.CreateBatchFromEventsHandler = (_e, _p) => mockEnvelope.Object; mockEnvelope .Setup(message => message.SerializedMessageSize) .Returns(0); var batch = new AmqpEventBatch(mockConverter, options); Assert.That(() => batch.AsEnumerable <EventData>(), Throws.InstanceOf <FormatException>()); }
public void ConstructorInitializesTheSizeToABatchEnvelope() { var batchEnvelopeSize = 767; var mockMessage = new Mock <AmqpMessage>(); var mockConverter = new InjectableMockConverter(); mockConverter.CreateBatchFromEventsHandler = (_e, _p) => mockMessage.Object; mockMessage .Setup(message => message.SerializedMessageSize) .Returns(batchEnvelopeSize); var batch = new AmqpEventBatch(mockConverter, new BatchOptions { MaximumizeInBytes = 27 }); Assert.That(batch.SizeInBytes, Is.EqualTo(batchEnvelopeSize)); }
public void DisposeClearsTheSize() { var mockMessage = new Mock <AmqpMessage>(); var mockConverter = new InjectableMockConverter(); mockConverter.CreateBatchFromEventsHandler = (_e, _p) => mockMessage.Object; mockMessage .Setup(message => message.SerializedMessageSize) .Returns(9959); var batch = new AmqpEventBatch(mockConverter, new BatchOptions { MaximumizeInBytes = 99 }); batch.Dispose(); Assert.That(batch.SizeInBytes, Is.EqualTo(0)); }
public void ClearClearsTheSize() { var mockMessage = new Mock <AmqpMessage>(); var mockConverter = new InjectableMockConverter { CreateBatchFromEventsHandler = (_e, _p) => mockMessage.Object }; mockMessage .Setup(message => message.SerializedMessageSize) .Returns(9959); var batch = new AmqpEventBatch(mockConverter, new CreateBatchOptions { MaximumSizeInBytes = 99 }, default); batch.Clear(); Assert.That(batch.SizeInBytes, Is.EqualTo(GetReservedSize(batch))); }
public void ResetBatchSequencingRemovesPublishingProperties() { var currentIndex = -1; var removeCount = 0; var options = new CreateBatchOptions { MaximumSizeInBytes = 5000 }; var eventMessages = new AmqpMessage[5]; var mockEnvelope = new Mock <AmqpMessage>(); var mockConverter = new InjectableMockConverter { CreateBatchFromMessagesHandler = (_e, _p) => mockEnvelope.Object, CreateMessageFromEventHandler = (_e, _p) => eventMessages[++currentIndex], RemovePublishingPropertiesFromAmqpMessageHandler = (_m) => ++ removeCount }; mockEnvelope .Setup(message => message.SerializedMessageSize) .Returns(0); for (var index = 0; index < eventMessages.Length; ++index) { eventMessages[index] = AmqpMessage.Create(new FramingData { Value = new ArraySegment <byte>(new byte[] { 0x66 }) }); } // Add the messages to the batch; all should be accepted. var batch = new AmqpEventBatch(mockConverter, options, default); for (var index = 0; index < eventMessages.Length; ++index) { Assert.That(batch.TryAdd(new EventData(new byte[0])), Is.True, $"The addition for index: { index } should fit and be accepted."); } // Sequence the batch and validate the final state. batch.ResetBatchSequencing(); Assert.That(removeCount, Is.EqualTo(eventMessages.Length), "The publishing properties for each event should have been removed."); }
public void TryAddHonorsTheMeasureSequenceNumber(bool measureSequenceNumber) { var maximumSize = 50; var batchEnvelopeSize = 0; var capturedSequence = default(int?); var options = new CreateBatchOptions { MaximumSizeInBytes = maximumSize }; var mockEnvelope = new Mock <AmqpMessage>(); var mockEvent = new Mock <AmqpMessage>(); var mockConverter = new InjectableMockConverter { CreateBatchFromEventsHandler = (_e, _p) => mockEnvelope.Object, CreateMessageFromEventHandler = (_e, _p) => { capturedSequence = _e.PendingPublishSequenceNumber; return(mockEvent.Object); } }; mockEnvelope .Setup(message => message.SerializedMessageSize) .Returns(batchEnvelopeSize); mockEvent .Setup(message => message.SerializedMessageSize) .Returns(maximumSize); var batch = new AmqpEventBatch(mockConverter, options, measureSequenceNumber); batch.TryAdd(EventGenerator.CreateEvents(1).Single()); var expectationConstraint = (measureSequenceNumber) ? Is.Not.Null : Is.Null; Assert.That(capturedSequence, expectationConstraint); }
public void DisposeClearsTheCount() { var currentIndex = -1; var options = new CreateBatchOptions { MaximumSizeInBytes = 5000 }; var eventMessages = new AmqpMessage[5]; var mockEnvelope = new Mock <AmqpMessage>(); var mockConverter = new InjectableMockConverter { CreateBatchFromEventsHandler = (_e, _p) => mockEnvelope.Object, CreateMessageFromEventHandler = (_e, _p) => eventMessages[++currentIndex] }; mockEnvelope .Setup(message => message.SerializedMessageSize) .Returns(0); for (var index = 0; index < eventMessages.Length; ++index) { eventMessages[index] = AmqpMessage.Create(new FramingData { Value = new ArraySegment <byte>(new byte[] { 0x66 }) }); } // Add the messages to the batch; all should be accepted. var batch = new AmqpEventBatch(mockConverter, options, default); for (var index = 0; index < eventMessages.Length; ++index) { Assert.That(batch.TryAdd(new EventData(new byte[0])), Is.True, $"The addition for index: { index } should fit and be accepted."); } // Dispose the batch and verify that each message has also been disposed. batch.Dispose(); Assert.That(batch.Count, Is.EqualTo(0), "The count should have been cleared when the batch was disposed."); }
public void TryAddResetsPublishingState() { var maximumSize = 50; var batchEnvelopeSize = 0; var capturedEvent = default(EventData); var options = new CreateBatchOptions { MaximumSizeInBytes = maximumSize }; var mockEnvelope = new Mock <AmqpMessage>(); var mockEvent = new Mock <AmqpMessage>(); var mockConverter = new InjectableMockConverter { CreateBatchFromEventsHandler = (_e, _p) => mockEnvelope.Object, CreateMessageFromEventHandler = (_e, _p) => { capturedEvent = _e; return(mockEvent.Object); } }; mockEnvelope .Setup(message => message.SerializedMessageSize) .Returns(batchEnvelopeSize); mockEvent .Setup(message => message.SerializedMessageSize) .Returns(maximumSize); var batch = new AmqpEventBatch(mockConverter, options, TransportProducerFeatures.IdempotentPublishing); batch.TryAdd(EventGenerator.CreateEvents(1).Single()); Assert.That(capturedEvent.PublishedSequenceNumber, Is.Null, "The final sequence should not have been set."); Assert.That(capturedEvent.PendingPublishSequenceNumber, Is.Null, "The pending sequence was not cleared."); Assert.That(capturedEvent.PendingProducerGroupId, Is.Null, "The group identifier was not cleared."); Assert.That(capturedEvent.PendingProducerOwnerLevel, Is.Null, "The owner level was not cleared."); }
public void TryAddRemovesTheMeasureSequenceNumber() { var maximumSize = 50; var batchEnvelopeSize = 0; var capturedEvent = default(EventData); var options = new CreateBatchOptions { MaximumSizeInBytes = maximumSize }; var mockEnvelope = new Mock <AmqpMessage>(); var mockEvent = new Mock <AmqpMessage>(); var mockConverter = new InjectableMockConverter { CreateBatchFromEventsHandler = (_e, _p) => mockEnvelope.Object, CreateMessageFromEventHandler = (_e, _p) => { capturedEvent = _e; return(mockEvent.Object); } }; mockEnvelope .Setup(message => message.SerializedMessageSize) .Returns(batchEnvelopeSize); mockEvent .Setup(message => message.SerializedMessageSize) .Returns(maximumSize); var batch = new AmqpEventBatch(mockConverter, options, true); batch.TryAdd(EventGenerator.CreateEvents(1).Single()); Assert.That(capturedEvent.PublishedSequenceNumber, Is.Null); }