public async Task SendAsyncTransformsSimpleEvents() { var sourceEvents = new[] { new EventData(Encoding.UTF8.GetBytes("FirstValue")), new EventData(Encoding.UTF8.GetBytes("Second")), new EventData(new byte[] { 0x11, 0x22, 0x33 }) }; var options = new SendOptions(); var mock = new ObservableSenderMock(new ClientMock(), null); var producer = new TrackOneEventHubProducer(_ => mock, Mock.Of <EventHubRetryPolicy>()); await producer.SendAsync(sourceEvents, options, CancellationToken.None); Assert.That(mock.SendCalledWithParameters, Is.Not.Null, "The Send request should have been delegated."); var sentEvents = mock.SendCalledWithParameters.Events.ToArray(); Assert.That(sentEvents.Length, Is.EqualTo(sourceEvents.Length), "The number of events sent should match the number of source events."); // The events should not only be structurally equivalent, the ordering of them should be preserved. Compare the // sequence in order and validate that the events in each position are equivalent. for (var index = 0; index < sentEvents.Length; ++index) { // If the system properties for the sent events was null, then normalize it to an empty // instance because the source event does not allow null. sentEvents[index].SystemProperties = sentEvents[index].SystemProperties ?? new TrackOne.EventData.SystemPropertiesCollection(); Assert.That(TrackOneComparer.IsEventDataEquivalent(sentEvents[index], sourceEvents[index]), Is.True, $"The sequence of events sent should match; they differ at index: { index }"); } }
public async Task SendAsyncTransformsComplexEvents() { var sourceEvents = new[] { new EventData(Encoding.UTF8.GetBytes("FirstValue")), new EventData(Encoding.UTF8.GetBytes("Second")), new EventData(new byte[] { 0x11, 0x22, 0x33 }) }; for (var index = 0; index < sourceEvents.Length; ++index) { sourceEvents[index].Properties["type"] = typeof(TrackOneEventHubProducer).Name; sourceEvents[index].Properties["arbitrary"] = index; } var options = new SendOptions(); var mock = new ObservableSenderMock(new ClientMock(), null); var producer = new TrackOneEventHubProducer(() => mock); await producer.SendAsync(sourceEvents, options, CancellationToken.None); Assert.That(mock.SendCalledWithParameters, Is.Not.Null, "The Send request should have been delegated."); var sentEvents = mock.SendCalledWithParameters.Events.ToArray(); Assert.That(sentEvents.Length, Is.EqualTo(sourceEvents.Length), "The number of events sent should match the number of source events."); // The events should not only be structurally equivilent, the ordering of them should be preserved. Compare the // sequence in order and validate that the events in each position are equivilent. for (var index = 0; index < sentEvents.Length; ++index) { Assert.That(TrackOneComparer.IsEventDataEquivalent(sentEvents[index], sourceEvents[index]), Is.True, $"The sequence of events sent should match; they differ at index: { index }"); } }
public async Task ProducerIsConstructedCorrectly() { var partition = "123"; var mock = new ObservableSenderMock(new ClientMock(), partition); var producer = new TrackOneEventHubProducer(() => mock); // Invoke an operation to force the producer to be lazily instantiated. Otherwise, // construction does not happen. await producer.SendAsync(new[] { new EventData(new byte[] { 0x12, 0x22 }) }, new SendOptions(), default); Assert.That(mock.ConstructedWithPartition, Is.EqualTo(partition)); }
public async Task SendAsyncForwardsThePartitionHashKey(string expectedHashKey) { var options = new SendOptions { PartitionKey = expectedHashKey }; var mock = new ObservableSenderMock(new ClientMock(), null); var producer = new TrackOneEventHubProducer(_ => mock, Mock.Of <EventHubRetryPolicy>()); await producer.SendAsync(new[] { new EventData(new byte[] { 0x43 }) }, options, CancellationToken.None); Assert.That(mock.SendCalledWithParameters, Is.Not.Null, "The Send request should have been delegated."); (_, var actualHashKey) = mock.SendCalledWithParameters; Assert.That(actualHashKey, Is.EqualTo(expectedHashKey), "The partition hash key should have been forwarded."); }
public async Task SendAsyncTransformsEventBatches() { var messages = new[] { AmqpMessage.Create(new Data { Value = new ArraySegment <byte>(new byte[] { 0x11 }) }), AmqpMessage.Create(new Data { Value = new ArraySegment <byte>(new byte[] { 0x22 }) }), AmqpMessage.Create(new Data { Value = new ArraySegment <byte>(new byte[] { 0x33 }) }), }; var options = new BatchOptions { MaximumizeInBytes = 30 }; var transportBatch = new TransportBatchMock { Messages = messages }; var batch = new EventDataBatch(transportBatch, options); var mock = new ObservableSenderMock(new ClientMock(), null); var producer = new TrackOneEventHubProducer(_ => mock, Mock.Of <EventHubRetryPolicy>()); await producer.SendAsync(batch, CancellationToken.None); Assert.That(mock.SendCalledWithParameters, Is.Not.Null, "The Send request should have been delegated."); var sentEvents = mock.SendCalledWithParameters.Events.ToArray(); Assert.That(sentEvents.Length, Is.EqualTo(messages.Length), "The number of events sent should match the number of source events."); Assert.That(sentEvents.Where(evt => evt.AmqpMessage == null).Any(), Is.False, "The events should have had an AMQP message populated at transform."); var sentMessages = sentEvents.Select(evt => evt.AmqpMessage).ToList(); for (var index = 0; index < messages.Length; ++index) { Assert.That(sentMessages.Contains(messages[index]), $"The message at index: { index } was not part of the set that was sent."); } foreach (var message in messages) { message.Dispose(); } }
public async Task ProducerIsConstructedCorrectly() { var partition = "123"; var retryPolicy = Mock.Of <EventHubRetryPolicy>(); var mock = new ObservableSenderMock(new ClientMock(), partition); var producer = new TrackOneEventHubProducer(_ => mock, retryPolicy); // Invoke an operation to force the producer to be lazily instantiated. Otherwise, // construction does not happen. await producer.SendAsync(new[] { new EventData(new byte[] { 0x12, 0x22 }) }, new SendOptions(), default); Assert.That(mock.ConstructedWithPartition, Is.EqualTo(partition)); var producerRetry = GetRetryPolicy(producer); Assert.That(producerRetry, Is.SameAs(retryPolicy), "The producer retry instance should match."); }
public async Task SendAsyncForwardsThePartitionHashKeyForBatches() { var messages = new[] { AmqpMessage.Create(new Data { Value = new ArraySegment <byte>(new byte[] { 0x11 }) }), AmqpMessage.Create(new Data { Value = new ArraySegment <byte>(new byte[] { 0x22 }) }), AmqpMessage.Create(new Data { Value = new ArraySegment <byte>(new byte[] { 0x33 }) }), }; var expectedHashKey = "TestKEy"; var options = new BatchOptions { MaximumizeInBytes = 30, PartitionKey = expectedHashKey }; var transportBatch = new TransportBatchMock { Messages = messages }; var batch = new EventDataBatch(transportBatch, options); var mock = new ObservableSenderMock(new ClientMock(), null); var producer = new TrackOneEventHubProducer(_ => mock, Mock.Of <EventHubRetryPolicy>()); await producer.SendAsync(batch, CancellationToken.None); Assert.That(mock.SendCalledWithParameters, Is.Not.Null, "The Send request should have been delegated."); (_, var actualHashKey) = mock.SendCalledWithParameters; Assert.That(actualHashKey, Is.EqualTo(expectedHashKey), "The partition hash key should have been forwarded."); foreach (var message in messages) { message.Dispose(); } }
public async Task CloseAsyncDoesNotDelegateIfTheSenderWasNotCreated() { var mock = new ObservableSenderMock(new ClientMock(), null); var producer = new TrackOneEventHubProducer(_ => mock, Mock.Of <EventHubRetryPolicy>()); await producer.CloseAsync(default);