public void SendRequiresTheBatch() { var transportProducer = new ObservableTransportProducerMock(); var producer = new EventHubProducer(transportProducer, new Uri("amqp://some.endpoint.com/path"), "dummy", new EventHubProducerOptions(), Mock.Of <EventHubRetryPolicy>()); Assert.That(async() => await producer.SendAsync(default(EventDataBatch)), Throws.ArgumentNullException); }
public async Task ProducerCanSendSetToASpecificPartition() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { var connectionString = TestEnvironment.BuildConnectionStringForEventHub(scope.EventHubName); await using (var client = new EventHubClient(connectionString)) { var partition = (await client.GetPartitionIdsAsync()).First(); var producerOptions = new EventHubProducerOptions { PartitionId = partition }; await using (EventHubProducer producer = client.CreateProducer(producerOptions)) { EventData[] events = new[] { new EventData(Encoding.UTF8.GetBytes("This is a message")), new EventData(Encoding.UTF8.GetBytes("This is another message")), new EventData(Encoding.UTF8.GetBytes("Do we need more messages")) }; Assert.That(async() => await producer.SendAsync(events), Throws.Nothing); } } } }
public async Task EventHubProducerCreatesDiagnosticScopeOnSend() { using var testListener = new ClientDiagnosticListener(DiagnosticSourceName); var eventHubName = "SomeName"; var endpoint = new Uri("amqp://endpoint"); var transportMock = new Mock <TransportEventHubProducer>(); transportMock .Setup(m => m.SendAsync(It.IsAny <IEnumerable <EventData> >(), It.IsAny <SendOptions>(), It.IsAny <CancellationToken>())) .Returns(Task.CompletedTask); var producer = new EventHubProducer(transportMock.Object, endpoint, eventHubName, new EventHubProducerOptions(), Mock.Of <EventHubRetryPolicy>()); var eventData = new EventData(ReadOnlyMemory <byte> .Empty); await producer.SendAsync(eventData); ClientDiagnosticListener.ProducedDiagnosticScope sendScope = testListener.AssertScope(DiagnosticProperty.ProducerActivityName, new KeyValuePair <string, string>(DiagnosticProperty.TypeAttribute, DiagnosticProperty.EventHubProducerType), new KeyValuePair <string, string>(DiagnosticProperty.ServiceContextAttribute, DiagnosticProperty.EventHubsServiceContext), new KeyValuePair <string, string>(DiagnosticProperty.EventHubAttribute, eventHubName), new KeyValuePair <string, string>(DiagnosticProperty.EndpointAttribute, endpoint.ToString())); ClientDiagnosticListener.ProducedDiagnosticScope messageScope = testListener.AssertScope(DiagnosticProperty.EventActivityName); Assert.That(eventData.Properties[DiagnosticProperty.DiagnosticIdAttribute], Is.EqualTo(messageScope.Activity.Id), "The diagnostics identifier should match."); Assert.That(messageScope.Activity.Tags, Has.One.EqualTo(new KeyValuePair <string, string>(DiagnosticProperty.KindAttribute, DiagnosticProperty.InternalKind)), "The activities tag should be internal."); Assert.That(messageScope.Activity, Is.Not.SameAs(sendScope.Activity), "The activities should not be the same instance."); }
public async Task ProducerCanSendLargeEventBatch() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { var connectionString = TestEnvironment.BuildConnectionStringForEventHub(scope.EventHubName); await using (var client = new EventHubClient(connectionString, new EventHubClientOptions { RetryOptions = new RetryOptions { TryTimeout = TimeSpan.FromMinutes(5) } })) await using (EventHubProducer producer = client.CreateProducer()) { using EventDataBatch batch = await producer.CreateBatchAsync(); // Actual limit is 1046520 for a single event. batch.TryAdd(new EventData(new byte[100000 / 3])); batch.TryAdd(new EventData(new byte[100000 / 3])); batch.TryAdd(new EventData(new byte[100000 / 3])); Assert.That(batch.Count, Is.EqualTo(3), "The batch should contain all 3 events."); Assert.That(async() => await producer.SendAsync(batch), Throws.Nothing); } } }
public async Task ProducerCanSendAnEventBatchUsingAPartitionHashKey() { await using (EventHubScope scope = await EventHubScope.CreateAsync(2)) { IEnumerable <EventData> events = Enumerable .Range(0, 25) .Select(index => new EventData(Encoding.UTF8.GetBytes(new string('X', index + 5)))); var connectionString = TestEnvironment.BuildConnectionStringForEventHub(scope.EventHubName); var batchOptions = new BatchOptions { PartitionKey = "some123key-!d" }; await using (var client = new EventHubClient(connectionString)) await using (EventHubProducer producer = client.CreateProducer()) { using EventDataBatch batch = await producer.CreateBatchAsync(batchOptions); foreach (EventData eventData in events) { Assert.That(() => batch.TryAdd(eventData), Is.True, "An event was rejected by the batch; all events should be accepted."); } Assert.That(async() => await producer.SendAsync(batch), Throws.Nothing); } } }
public async Task ProducerCanSendLargeSet() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { var connectionString = TestEnvironment.BuildConnectionStringForEventHub(scope.EventHubName); await using (var client = new EventHubClient(connectionString, new EventHubClientOptions { RetryOptions = new RetryOptions { TryTimeout = TimeSpan.FromMinutes(5) } })) await using (EventHubProducer producer = client.CreateProducer()) { // Actual limit is 1046520 for a single event. EventData[] events = new[] { new EventData(new byte[100000 / 3]), new EventData(new byte[100000 / 3]), new EventData(new byte[100000 / 3]) }; Assert.That(async() => await producer.SendAsync(events), Throws.Nothing); } } }
public void ConstructorSetsTheRetryPolicy() { EventHubRetryPolicy retryPolicy = Mock.Of <EventHubRetryPolicy>(); var producer = new EventHubProducer(new ObservableTransportProducerMock(), new Uri("amqp://some.endpoint.com/path"), "path", new EventHubProducerOptions(), retryPolicy); Assert.That(producer.RetryPolicy, Is.SameAs(retryPolicy)); }
public async Task ProducerCanSendEventsWithCustomProperties() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { EventData[] events = new[] { new EventData(new byte[] { 0x22, 0x33 }), new EventData(Encoding.UTF8.GetBytes("This is a really long string of stuff that I wanted to type because I like to")), new EventData(Encoding.UTF8.GetBytes("I wanted to type because I like to")), new EventData(Encoding.UTF8.GetBytes("If you are reading this, you really like test cases")) }; for (var index = 0; index < events.Length; ++index) { events[index].Properties[index.ToString()] = "some value"; events[index].Properties["Type"] = $"com.microsoft.test.Type{ index }"; } var connectionString = TestEnvironment.BuildConnectionStringForEventHub(scope.EventHubName); await using (var client = new EventHubClient(connectionString)) await using (EventHubProducer producer = client.CreateProducer()) { Assert.That(async() => await producer.SendAsync(events), Throws.Nothing); } } }
public void SendSingleWithoutOptionsRequiresAnEvent() { var transportProducer = new ObservableTransportProducerMock(); var producer = new EventHubProducer(transportProducer, "dummy", new EventHubProducerOptions(), Mock.Of <EventHubRetryPolicy>()); Assert.That(async() => await producer.SendAsync(default(EventData)), Throws.ArgumentNullException); }
public void SendRequiresEvents() { var transportProducer = new ObservableTransportProducerMock(); var producer = new EventHubProducer(transportProducer, "dummy", new EventHubProducerOptions(), Mock.Of <EventHubRetryPolicy>()); Assert.That(async() => await producer.SendAsync(default(IEnumerable <EventData>), new SendOptions()), Throws.ArgumentNullException); }
public void ConstructorSetsTheRetryPolicy() { var retryPolicy = Mock.Of <EventHubRetryPolicy>(); var producer = new EventHubProducer(new ObservableTransportProducerMock(), "path", new EventHubProducerOptions(), retryPolicy); Assert.That(producer.RetryPolicy, Is.SameAs(retryPolicy)); }
public async Task EventHubProducerAppliesDiagnosticIdToEventsOnSend() { Activity activity = new Activity("SomeActivity").Start(); var eventHubName = "SomeName"; var endpoint = new Uri("amqp://some.endpoint.com/path"); var transportMock = new Mock <TransportEventHubProducer>(); EventData[] writtenEventsData = null; transportMock .Setup(m => m.SendAsync(It.IsAny <IEnumerable <EventData> >(), It.IsAny <SendOptions>(), It.IsAny <CancellationToken>())) .Callback <IEnumerable <EventData>, SendOptions, CancellationToken>((e, _, __) => writtenEventsData = e.ToArray()) .Returns(Task.CompletedTask); var producer = new EventHubProducer(transportMock.Object, endpoint, eventHubName, new EventHubProducerOptions(), Mock.Of <EventHubRetryPolicy>()); await producer.SendAsync(new[] { new EventData(ReadOnlyMemory <byte> .Empty), new EventData(ReadOnlyMemory <byte> .Empty) }); activity.Stop(); Assert.That(writtenEventsData.Length, Is.EqualTo(2), "All events should have been instrumented."); foreach (EventData eventData in writtenEventsData) { Assert.That(eventData.Properties.TryGetValue(DiagnosticProperty.DiagnosticIdAttribute, out object value), Is.True, "The events should have a diagnostic identifier property."); Assert.That(value, Is.EqualTo(activity.Id), "The diagnostics identifier should match the activity in the active scope."); } }
public void SettingTheRetryUpdatesState() { var retryOptions = new RetryOptions { Delay = TimeSpan.FromSeconds(1), MaximumDelay = TimeSpan.FromSeconds(2), TryTimeout = TimeSpan.FromSeconds(3), MaximumRetries = 4, Mode = RetryMode.Fixed }; var customRetry = Mock.Of <EventHubRetryPolicy>(); var producerOptions = new EventHubProducerOptions { RetryOptions = retryOptions }; var producer = new EventHubProducer(new ObservableTransportProducerMock(), "dummy", producerOptions, new BasicRetryPolicy(retryOptions)); Assert.That(producer.RetryPolicy, Is.InstanceOf <BasicRetryPolicy>(), "The retry policy should have been created from options"); producer.RetryPolicy = customRetry; Assert.That(producer.RetryPolicy, Is.SameAs(customRetry), "The custom retry policy should have been set."); var activeOptions = (EventHubProducerOptions) typeof(EventHubProducer) .GetProperty("Options", BindingFlags.Instance | BindingFlags.NonPublic) .GetValue(producer); Assert.That(activeOptions.RetryOptions, Is.Null, "Setting a custom policy should clear the retry options."); }
public async Task ProducerCannotSendWhenClosed(bool sync) { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { var connectionString = TestEnvironment.BuildConnectionStringForEventHub(scope.EventHubName); await using (var client = new EventHubClient(connectionString)) await using (EventHubProducer producer = client.CreateProducer()) { EventData[] events = new[] { new EventData(Encoding.UTF8.GetBytes("Dummy event")) }; Assert.That(async() => await producer.SendAsync(events), Throws.Nothing); if (sync) { producer.Close(); } else { await producer.CloseAsync(); } Assert.That(async() => await producer.SendAsync(events), Throws.TypeOf <EventHubsClientClosedException>().Or.TypeOf <ObjectDisposedException>()); } } }
public async Task CloseAsyncClosesTheTransportProducer() { var transportProducer = new ObservableTransportProducerMock(); var producer = new EventHubProducer(transportProducer, new Uri("amqp://some.endpoint.com/path"), "dummy", new EventHubProducerOptions(), Mock.Of <EventHubRetryPolicy>()); await producer.CloseAsync(); Assert.That(transportProducer.WasCloseCalled, Is.True); }
public async Task CloseAsyncClosesTheTransportProducer() { var transportProducer = new ObservableTransportProducerMock(); var producer = new EventHubProducer(transportProducer, "dummy", new EventHubProducerOptions()); await producer.CloseAsync(); Assert.That(transportProducer.WasCloseCalled, Is.True); }
public void CloseClosesTheTransportProducer() { var transportProducer = new ObservableTransportProducerMock(); var producer = new EventHubProducer(transportProducer, "dummy", new EventHubProducerOptions(), Mock.Of <EventHubRetryPolicy>()); producer.Close(); Assert.That(transportProducer.WasCloseCalled, Is.True); }
/// <summary> /// Creates a size-constraint batch to which <see cref="EventData" /> may be added using a try-based pattern. If an event would /// exceed the maximum allowable size of the batch, the batch will not allow adding the event and signal that scenario using its /// return value. /// /// Because events that would violate the size constraint cannot be added, publishing a batch will not trigger an exception when /// attempting to send the events to the Event Hubs service. /// </summary> /// /// <param name="options">The set of options to consider when creating this batch.</param> /// <param name="cancellationToken">An optional <see cref="CancellationToken"/> instance to signal the request to cancel the operation.</param> /// /// <returns>An <see cref="EventDataBatch" /> with the requested <paramref name="options"/>.</returns> /// /// <seealso cref="CreateBatchAsync(CreateBatchOptions, CancellationToken)" /> /// public virtual async ValueTask <EventDataBatch> CreateBatchAsync(CreateBatchOptions options, CancellationToken cancellationToken = default) { options = options?.Clone() ?? new CreateBatchOptions(); AssertSinglePartitionReference(options.PartitionId, options.PartitionKey); TransportEventBatch transportBatch = await EventHubProducer.CreateBatchAsync(options, cancellationToken).ConfigureAwait(false); return(new EventDataBatch(transportBatch, FullyQualifiedNamespace, EventHubName, options.ToSendOptions())); }
public void SettingTheRetryUpdatesTheTransportProducer() { var customRetry = Mock.Of <EventHubRetryPolicy>(); var transportProducer = new ObservableTransportProducerMock(); var producerOptions = new EventHubProducerOptions(); var producer = new EventHubProducer(transportProducer, "dummy", producerOptions, Mock.Of <EventHubRetryPolicy>()); producer.RetryPolicy = customRetry; Assert.That(transportProducer.UpdateRetryPolicyCalledWith, Is.SameAs(customRetry), "The custom retry policy should have been passed to the transport producer."); }
public async Task EventHubProducerAppliesDiagnosticIdToEventsOnBatchSend() { Activity activity = new Activity("SomeActivity").Start(); var eventHubName = "SomeName"; var endpoint = new Uri("amqp://some.endpoint.com/path"); var writtenEventsData = new List <EventData>(); var batchTransportMock = new Mock <TransportEventBatch>(); var transportMock = new Mock <TransportEventHubProducer>(); batchTransportMock .Setup(m => m.TryAdd(It.IsAny <EventData>())) .Returns <EventData>(e => { var hasSpace = writtenEventsData.Count <= 1; if (hasSpace) { writtenEventsData.Add(e); } return(hasSpace); }); transportMock .Setup(m => m.SendAsync(It.IsAny <IEnumerable <EventData> >(), It.IsAny <SendOptions>(), It.IsAny <CancellationToken>())) .Returns(Task.CompletedTask); transportMock .Setup(m => m.CreateBatchAsync(It.IsAny <BatchOptions>(), It.IsAny <CancellationToken>())) .Returns(new ValueTask <TransportEventBatch>(Task.FromResult(batchTransportMock.Object))); var producer = new EventHubProducer(transportMock.Object, endpoint, eventHubName, new EventHubProducerOptions(), Mock.Of <EventHubRetryPolicy>()); var eventData1 = new EventData(ReadOnlyMemory <byte> .Empty); var eventData2 = new EventData(ReadOnlyMemory <byte> .Empty); var eventData3 = new EventData(ReadOnlyMemory <byte> .Empty); EventDataBatch batch = await producer.CreateBatchAsync(); Assert.That(batch.TryAdd(eventData1), Is.True, "The first event should have been added to the batch."); Assert.That(batch.TryAdd(eventData2), Is.True, "The second event should have been added to the batch."); Assert.That(batch.TryAdd(eventData3), Is.False, "The third event should not have been added to the batch."); await producer.SendAsync(batch); activity.Stop(); Assert.That(writtenEventsData.Count, Is.EqualTo(2), "Each of the events in the batch should have been instrumented."); foreach (EventData eventData in writtenEventsData) { Assert.That(eventData.Properties.TryGetValue(DiagnosticProperty.DiagnosticIdAttribute, out object value), Is.True, "The events should have a diagnostic identifier property."); Assert.That(value, Is.EqualTo(activity.Id), "The diagnostics identifier should match the activity in the active scope."); } Assert.That(eventData3.Properties.ContainsKey(DiagnosticProperty.DiagnosticIdAttribute), Is.False, "Events that were not accepted into the batch should not have been instrumented."); }
public void SendAllowsAPartitionHashKeyWithABatch() { var batchOptions = new BatchOptions { PartitionKey = "testKey" }; var batch = new EventDataBatch(new MockTransportBatch(), batchOptions); var transportProducer = new ObservableTransportProducerMock(); var producer = new EventHubProducer(transportProducer, new Uri("amqp://some.endpoint.com/path"), "dummy", new EventHubProducerOptions(), Mock.Of <EventHubRetryPolicy>()); Assert.That(async() => await producer.SendAsync(batch), Throws.Nothing); }
public void SendAllowsAPartitionHashKey() { var batchingOptions = new SendOptions { PartitionKey = "testKey" }; var events = new[] { new EventData(new byte[] { 0x44, 0x66, 0x88 }) }; var transportProducer = new ObservableTransportProducerMock(); var producer = new EventHubProducer(transportProducer, "dummy", new EventHubProducerOptions(), Mock.Of <EventHubRetryPolicy>()); Assert.That(async() => await producer.SendAsync(events, batchingOptions), Throws.Nothing); }
public void CreateBatchForASpecificPartitionDoesNotAllowAPartitionHashKey() { var batchOptions = new BatchOptions { PartitionKey = "testKey" }; var transportProducer = new ObservableTransportProducerMock(); var producer = new EventHubProducer(transportProducer, new Uri("amqp://some.endpoint.com/path"), "dummy", new EventHubProducerOptions { PartitionId = "1" }, Mock.Of <EventHubRetryPolicy>()); Assert.That(async() => await producer.CreateBatchAsync(batchOptions), Throws.InvalidOperationException); }
public async Task CreateBatchSetsTheSendOptionsForTheEventBatch() { var batchOptions = new BatchOptions { PartitionKey = "Hi", MaximumizeInBytes = 9999 }; var transportProducer = new ObservableTransportProducerMock(); var producer = new EventHubProducer(transportProducer, new Uri("amqp://some.endpoint.com/path"), "dummy", new EventHubProducerOptions(), Mock.Of <EventHubRetryPolicy>()); EventDataBatch eventBatch = await producer.CreateBatchAsync(batchOptions); Assert.That(eventBatch.SendOptions, Is.SameAs(transportProducer.CreateBatchCalledWith), "The batch options should have used for the send options."); ; }
public void SettingTheRetryUpdatesTheTransportProducer() { EventHubRetryPolicy customRetry = Mock.Of <EventHubRetryPolicy>(); var transportProducer = new ObservableTransportProducerMock(); var producerOptions = new EventHubProducerOptions(); var producer = new EventHubProducer(transportProducer, new Uri("amqp://some.endpoint.com/path"), "dummy", producerOptions, Mock.Of <EventHubRetryPolicy>()) { RetryPolicy = customRetry }; Assert.That(transportProducer.UpdateRetryPolicyCalledWith, Is.SameAs(customRetry), "The custom retry policy should have been passed to the transport producer."); }
public async Task SendInvokesTheTransportProducerWithABatch() { var batchOptions = new BatchOptions { PartitionKey = "testKey" }; var batch = new EventDataBatch(new MockTransportBatch(), batchOptions); var transportProducer = new ObservableTransportProducerMock(); var producer = new EventHubProducer(transportProducer, new Uri("amqp://some.endpoint.com/path"), "dummy", new EventHubProducerOptions(), Mock.Of <EventHubRetryPolicy>()); await producer.SendAsync(batch); Assert.That(transportProducer.SendBatchCalledWith, Is.SameAs(batch), "The batch should be the same instance."); }
public async Task SendWithoutOptionsInvokesTheTransportProducer() { var events = Mock.Of <IEnumerable <EventData> >(); var transportProducer = new ObservableTransportProducerMock(); var producer = new EventHubProducer(transportProducer, "dummy", new EventHubProducerOptions(), Mock.Of <EventHubRetryPolicy>()); await producer.SendAsync(events); (var calledWithEvents, var calledWithOptions) = transportProducer.SendCalledWith; Assert.That(calledWithEvents, Is.SameAs(events), "The events should be the same instance."); Assert.That(calledWithOptions, Is.Not.Null, "A default set of options should be used."); }
public void SendForASpecificPartitionDoesNotAllowAPartitionHashKey() { var batchingOptions = new SendOptions { PartitionKey = "testKey" }; var events = new[] { new EventData(new byte[] { 0x44, 0x66, 0x88 }) }; var transportProducer = new ObservableTransportProducerMock(); var producer = new EventHubProducer(transportProducer, "dummy", new EventHubProducerOptions { PartitionId = "1" }, Mock.Of <EventHubRetryPolicy>()); Assert.That(async() => await producer.SendAsync(events, batchingOptions), Throws.InvalidOperationException); }
public async Task CreateBatchDefaultsBatchOptions() { var expectedOptions = new BatchOptions(); var transportProducer = new ObservableTransportProducerMock(); var producer = new EventHubProducer(transportProducer, new Uri("amqp://some.endpoint.com/path"), "dummy", new EventHubProducerOptions(), Mock.Of <EventHubRetryPolicy>()); await producer.CreateBatchAsync(); Assert.That(transportProducer.CreateBatchCalledWith, Is.Not.Null, "The batch creation should have passed options."); Assert.That(transportProducer.CreateBatchCalledWith, Is.Not.SameAs(expectedOptions), "The options should have been cloned."); Assert.That(transportProducer.CreateBatchCalledWith.PartitionKey, Is.EqualTo(expectedOptions.PartitionKey), "The partition key should match."); Assert.That(transportProducer.CreateBatchCalledWith.MaximumizeInBytes, Is.EqualTo(expectedOptions.MaximumizeInBytes), "The maximum size should match."); }
public async Task SendWithoutOptionsInvokesTheTransportProducer() { var events = new EventData[0]; var transportProducer = new ObservableTransportProducerMock(); var producer = new EventHubProducer(transportProducer, new Uri("amqp://some.endpoint.com/path"), "dummy", new EventHubProducerOptions(), Mock.Of <EventHubRetryPolicy>()); await producer.SendAsync(events); (IEnumerable <EventData> calledWithEvents, SendOptions calledWithOptions) = transportProducer.SendCalledWith; Assert.That(calledWithEvents, Is.EquivalentTo(events), "The events should contain same elements."); Assert.That(calledWithOptions, Is.Not.Null, "A default set of options should be used."); }