public async Task ConnectionCanConnectToEventHubsUsingArguments() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { var options = new EventHubConnectionOptions(); var connectionString = TestEnvironment.BuildConnectionStringForEventHub(scope.EventHubName); var connectionProperties = ConnectionStringParser.Parse(connectionString); var credential = new SharedAccessSignatureCredential ( new SharedAccessSignature ( $"{ options.TransportType.GetUriScheme() }://{ connectionProperties.Endpoint.Host }/{ connectionProperties.EventHubName }".ToLowerInvariant(), connectionProperties.SharedAccessKeyName, connectionProperties.SharedAccessKey, TimeSpan.FromHours(4) ) ); await using (var connection = new TestConnectionWithTransport(connectionProperties.Endpoint.Host, connectionProperties.EventHubName, credential)) { Assert.That(() => connection.GetPropertiesAsync(), Throws.Nothing); } } }
public async Task ConnectionTransportCannotRetrieveMetadataWhenProxyIsInvalid() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var retryOptions = new EventHubsRetryOptions { TryTimeout = TimeSpan.FromMinutes(2) }; var clientOptions = new EventHubConnectionOptions { Proxy = new WebProxy("http://1.2.3.4:9999"), TransportType = EventHubsTransportType.AmqpWebSockets }; await using (var connection = new TestConnectionWithTransport(connectionString)) await using (var invalidProxyConnection = new TestConnectionWithTransport(connectionString, clientOptions)) { connection.RetryPolicy = new BasicRetryPolicy(retryOptions); invalidProxyConnection.RetryPolicy = new BasicRetryPolicy(retryOptions); var partition = (await connection.GetPartitionIdsAsync()).First(); Assert.That(async() => await invalidProxyConnection.GetPartitionIdsAsync(), Throws.InstanceOf <WebSocketException>().Or.InstanceOf <TimeoutException>()); Assert.That(async() => await invalidProxyConnection.GetPropertiesAsync(), Throws.InstanceOf <WebSocketException>().Or.InstanceOf <TimeoutException>()); Assert.That(async() => await invalidProxyConnection.GetPartitionPropertiesAsync(partition), Throws.InstanceOf <WebSocketException>().Or.InstanceOf <TimeoutException>()); } } }
/// <summary> /// Initializes a new instance of the <see cref="AmqpClient"/> class. /// </summary> /// /// <param name="host">The fully qualified host name for the Event Hubs namespace. This is likely to be similar to <c>{yournamespace}.servicebus.windows.net</c>.</param> /// <param name="eventHubName">The name of the specific Event Hub to connect the client to.</param> /// <param name="operationTimeout">The amount of time to allow for an AMQP operation using the link to complete before attempting to cancel it.</param> /// <param name="credential">The Azure managed identity credential to use for authorization. Access controls may be specified by the Event Hubs namespace or the requested Event Hub, depending on Azure configuration.</param> /// <param name="clientOptions">A set of options to apply when configuring the client.</param> /// /// <remarks> /// As an internal type, this class performs only basic sanity checks against its arguments. It /// is assumed that callers are trusted and have performed deep validation. /// /// Any parameters passed are assumed to be owned by this instance and safe to mutate or dispose; /// creation of clones or otherwise protecting the parameters is assumed to be the purview of the /// caller. /// </remarks> /// public AmqpClient(string host, string eventHubName, TimeSpan operationTimeout, EventHubTokenCredential credential, EventHubConnectionOptions clientOptions) : this(host, eventHubName, operationTimeout, credential, clientOptions, null, null) { }
/// <summary> /// Creates a new copy of the current <see cref="EventHubConnectionOptions" />, cloning its attributes into a new instance. /// </summary> /// /// <param name="instance">The instance that this method was invoked on.</param> /// /// <returns>A new copy of <see cref="EventHubConnectionOptions" />.</returns> /// public static EventHubConnectionOptions Clone(this EventHubConnectionOptions instance) => new EventHubConnectionOptions { TransportType = instance.TransportType, Proxy = instance.Proxy, CustomEndpointAddress = instance.CustomEndpointAddress };
public InjectableTransportClientMock(TransportClient transportClient, string connectionString, EventHubConnectionOptions clientOptions = default) : base(connectionString, clientOptions) { TransportClient = transportClient; SetTransportClient(transportClient); }
public void RespectsConnectionOptionsForProducer(string expectedPathName, string connectionString) { var testEndpoint = new Uri("http://mycustomendpoint.com"); EventHubOptions options = new EventHubOptions { CustomEndpointAddress = testEndpoint, ClientRetryOptions = new EventHubsRetryOptions { MaximumRetries = 10 } }; var configuration = CreateConfiguration(new KeyValuePair <string, string>("connection", connectionString)); var factory = CreateFactory(configuration, options); var producer = factory.GetEventHubProducerClient(expectedPathName, "connection"); EventHubConnection connection = (EventHubConnection)typeof(EventHubProducerClient).GetProperty("Connection", BindingFlags.NonPublic | BindingFlags.Instance) .GetValue(producer); EventHubConnectionOptions connectionOptions = (EventHubConnectionOptions)typeof(EventHubConnection).GetProperty("Options", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(connection); Assert.AreEqual(testEndpoint, connectionOptions.CustomEndpointAddress); Assert.AreEqual(expectedPathName, producer.EventHubName); EventHubProducerClientOptions producerOptions = (EventHubProducerClientOptions)typeof(EventHubProducerClient).GetProperty("Options", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(producer); Assert.AreEqual(10, producerOptions.RetryOptions.MaximumRetries); Assert.AreEqual(expectedPathName, producer.EventHubName); }
/// <summary> /// Initializes a new instance of the <see cref="AmqpClient"/> class. /// </summary> /// /// <param name="host">The fully qualified host name for the Event Hubs namespace. This is likely to be similar to <c>{yournamespace}.servicebus.windows.net</c>.</param> /// <param name="eventHubName">The name of the specific Event Hub to connect the client to.</param> /// <param name="credential">The Azure managed identity credential to use for authorization. Access controls may be specified by the Event Hubs namespace or the requested Event Hub, depending on Azure configuration.</param> /// <param name="clientOptions">A set of options to apply when configuring the client.</param> /// <param name="connectionScope">The optional scope to use for AMQP connection management. If <c>null</c>, a new scope will be created.</param> /// <param name="messageConverter">The optional converter to use for transforming AMQP message-related types. If <c>null</c>, a new converter will be created.</param> /// /// <remarks> /// As an internal type, this class performs only basic sanity checks against its arguments. It /// is assumed that callers are trusted and have performed deep validation. /// /// Any parameters passed are assumed to be owned by this instance and safe to mutate or dispose; /// creation of clones or otherwise protecting the parameters is assumed to be the purview of the /// caller. /// </remarks> /// protected AmqpClient(string host, string eventHubName, EventHubTokenCredential credential, EventHubConnectionOptions clientOptions, AmqpConnectionScope connectionScope, AmqpMessageConverter messageConverter) { Argument.AssertNotNullOrEmpty(host, nameof(host)); Argument.AssertNotNullOrEmpty(eventHubName, nameof(eventHubName)); Argument.AssertNotNull(credential, nameof(credential)); Argument.AssertNotNull(clientOptions, nameof(clientOptions)); try { EventHubsEventSource.Log.EventHubClientCreateStart(host, eventHubName); ServiceEndpoint = new UriBuilder { Scheme = clientOptions.TransportType.GetUriScheme(), Host = host }.Uri; EventHubName = eventHubName; Credential = credential; MessageConverter = messageConverter ?? new AmqpMessageConverter(); ConnectionScope = connectionScope ?? new AmqpConnectionScope(ServiceEndpoint, eventHubName, credential, clientOptions.TransportType, clientOptions.Proxy); ManagementLink = new FaultTolerantAmqpObject <RequestResponseAmqpLink>(timeout => ConnectionScope.OpenManagementLinkAsync(timeout, CancellationToken.None), link => link.SafeClose()); } finally { EventHubsEventSource.Log.EventHubClientCreateComplete(host, eventHubName); } }
public void RespectsConnectionOptionsForProducer(string expectedPathName, string connectionString) { var testEndpoint = new Uri("http://mycustomendpoint.com"); EventHubOptions options = new EventHubOptions { ConnectionOptions = new EventHubConnectionOptions { CustomEndpointAddress = testEndpoint }, RetryOptions = new EventHubsRetryOptions { MaximumRetries = 10 } }; options.AddSender(expectedPathName, connectionString); var configuration = CreateConfiguration(); var factory = new EventHubClientFactory(configuration, Mock.Of <AzureComponentFactory>(), Options.Create(options), new DefaultNameResolver(configuration)); var producer = factory.GetEventHubProducerClient(expectedPathName, null); EventHubConnection connection = (EventHubConnection)typeof(EventHubProducerClient).GetProperty("Connection", BindingFlags.NonPublic | BindingFlags.Instance) .GetValue(producer); EventHubConnectionOptions connectionOptions = (EventHubConnectionOptions)typeof(EventHubConnection).GetProperty("Options", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(connection); Assert.AreEqual(testEndpoint, connectionOptions.CustomEndpointAddress); Assert.AreEqual(expectedPathName, producer.EventHubName); EventHubProducerClientOptions producerOptions = (EventHubProducerClientOptions)typeof(EventHubProducerClient).GetProperty("Options", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(producer); Assert.AreEqual(10, producerOptions.RetryOptions.MaximumRetries); Assert.AreEqual(expectedPathName, producer.EventHubName); }
public void CreateConsumerCreatesDefaultWhenOptionsAreNotSet() { var retryOptions = new RetryOptions { MaximumRetries = 99, MaximumDelay = TimeSpan.FromHours(72), Delay = TimeSpan.FromSeconds(27) }; var expectedOptions = new EventHubConsumerClientOptions { OwnerLevel = 251, PrefetchCount = 600, RetryOptions = retryOptions, DefaultMaximumReceiveWaitTime = TimeSpan.FromSeconds(123) }; var clientOptions = new EventHubConnectionOptions(); var expectedConsumerGroup = "SomeGroup"; var expectedPartition = "56767"; var expectedPosition = EventPosition.FromSequenceNumber(123); var connectionString = "Endpoint=value.com;SharedAccessKeyName=[value];SharedAccessKey=[value];EntityPath=[value]"; var mockClient = new ReadableOptionsMock(connectionString, clientOptions); mockClient.CreateTransportConsumer(expectedConsumerGroup, expectedPartition, expectedPosition, expectedOptions); EventHubConsumerClientOptions actualOptions = mockClient.ConsumerOptions; Assert.That(actualOptions, Is.Not.Null, "The consumer options should have been set."); Assert.That(actualOptions, Is.Not.SameAs(expectedOptions), "A clone of the options should have been made."); Assert.That(actualOptions.OwnerLevel, Is.EqualTo(expectedOptions.OwnerLevel), "The owner levels should match."); Assert.That(actualOptions.PrefetchCount, Is.EqualTo(expectedOptions.PrefetchCount), "The prefetch counts should match."); Assert.That(actualOptions.RetryOptions.IsEquivalentTo(expectedOptions.RetryOptions), Is.True, "The retries should match."); Assert.That(actualOptions.MaximumReceiveWaitTimeOrDefault, Is.EqualTo(expectedOptions.MaximumReceiveWaitTimeOrDefault), "The wait times should match."); }
public async Task ConnectionTransportCannotRetrieveMetadataWhenCustomValidationRejectsTheCertificate() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var retryOptions = new EventHubsRetryOptions { TryTimeout = TimeSpan.FromMinutes(2) }; var clientOptions = new EventHubConnectionOptions { CertificateValidationCallback = (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) => false }; await using (var connection = new TestConnectionWithRetryPolicy(connectionString)) await using (var certificateRejectingConnection = new TestConnectionWithRetryPolicy(connectionString, clientOptions)) { connection.RetryPolicy = new BasicRetryPolicy(retryOptions); certificateRejectingConnection.RetryPolicy = new BasicRetryPolicy(retryOptions); var partition = (await connection.GetPartitionIdsAsync()).First(); Assert.That(async() => await certificateRejectingConnection.GetPartitionIdsAsync(), Throws.InstanceOf <AuthenticationException>()); Assert.That(async() => await certificateRejectingConnection.GetPropertiesAsync(), Throws.InstanceOf <AuthenticationException>()); Assert.That(async() => await certificateRejectingConnection.GetPartitionPropertiesAsync(partition), Throws.InstanceOf <AuthenticationException>()); } } }
public InjectableMockClient(string host, string eventHubName, EventHubTokenCredential credential, EventHubConnectionOptions clientOptions, AmqpConnectionScope connectionScope, AmqpMessageConverter messageConverter) : base(host, eventHubName, credential, clientOptions, connectionScope, messageConverter) { }
internal override TransportClient CreateTransportClient(string fullyQualifiedNamespace, string eventHubName, EventHubTokenCredential credential, EventHubConnectionOptions options) { TransportClientCredential = credential; return(TransportClient); }
public void ConstructorWithExpandedArgumentsValidatesOptions() { var invalidOptions = new EventHubConnectionOptions { TransportType = TransportType.AmqpTcp, Proxy = Mock.Of <IWebProxy>() }; Assert.That(() => new EventHubConnection("fullyQualifiedNamespace", "path", Mock.Of <TokenCredential>(), invalidOptions), Throws.ArgumentException, "The expanded argument constructor should validate client options"); }
public void ConstructorWithConnectionStringValidatesOptions() { var fakeConnection = "Endpoint=sb://not-real.servicebus.windows.net/;SharedAccessKeyName=DummyKey;SharedAccessKey=[not_real];EntityPath=fake"; var invalidOptions = new EventHubConnectionOptions { TransportType = TransportType.AmqpTcp, Proxy = Mock.Of <IWebProxy>() }; Assert.That(() => new EventHubConnection(fakeConnection, invalidOptions), Throws.ArgumentException, "The connection string constructor should validate client options"); }
public InjectableTransportClientMock(TransportClient transportClient, string fullyQualifiedNamespace, string eventHubName, TokenCredential credential, EventHubConnectionOptions clientOptions = default) : base(fullyQualifiedNamespace, eventHubName, credential, clientOptions) { TransportClient = transportClient; SetTransportClient(transportClient); }
/// <summary> /// Creates a new copy of the current <see cref="EventHubConnectionOptions" />, cloning its attributes into a new instance. /// </summary> /// /// <param name="instance">The instance that this method was invoked on.</param> /// /// <returns>A new copy of <see cref="EventHubConnectionOptions" />.</returns> /// public static EventHubConnectionOptions Clone(this EventHubConnectionOptions instance) => new EventHubConnectionOptions { TransportType = instance.TransportType, Proxy = instance.Proxy, CustomEndpointAddress = instance.CustomEndpointAddress, SendBufferSizeInBytes = instance.SendBufferSizeInBytes, ReceiveBufferSizeInBytes = instance.ReceiveBufferSizeInBytes, CertificateValidationCallback = instance.CertificateValidationCallback };
public void ConstructorInitializesTheEndpointsWithDefaults() { var options = new EventHubConnectionOptions(); var endpoint = new Uri("http://my.endpoint.com"); var credential = new Mock <EventHubTokenCredential>(Mock.Of <TokenCredential>()); var client = new AmqpClient(endpoint.Host, "somePath", credential.Object, options); Assert.That(client.ConnectionEndpoint.Host, Is.EqualTo(endpoint.Host), "The connection endpoint should have used the namespace URI."); Assert.That(client.ServiceEndpoint.Host, Is.EqualTo(endpoint.Host), "The service endpoint should have used the namespace URI."); }
public void TransportClientReceivesDefaultOptions(ReadableOptionsMock client, string constructorDescription) { var defaultOptions = new EventHubConnectionOptions(); EventHubConnectionOptions options = client.TransportClientOptions; Assert.That(options, Is.Not.Null, $"The { constructorDescription } constructor should have set default options."); Assert.That(options, Is.Not.SameAs(defaultOptions), $"The { constructorDescription } constructor should not have the same options instance."); Assert.That(options.TransportType, Is.EqualTo(defaultOptions.TransportType), $"The { constructorDescription } constructor should have the correct connection type."); Assert.That(options.Proxy, Is.EqualTo(defaultOptions.Proxy), $"The { constructorDescription } constructor should have the correct proxy."); }
public void TransportClientReceivesClonedOptions(ReadableOptionsMock client, EventHubConnectionOptions constructorOptions, string constructorDescription) { EventHubConnectionOptions options = client.TransportClientOptions; Assert.That(options, Is.Not.Null, $"The { constructorDescription } constructor should have set the options."); Assert.That(options, Is.Not.SameAs(constructorOptions), $"The { constructorDescription } constructor should have cloned the options."); Assert.That(options.TransportType, Is.EqualTo(constructorOptions.TransportType), $"The { constructorDescription } constructor should have the correct connection type."); Assert.That(options.Proxy, Is.EqualTo(constructorOptions.Proxy), $"The { constructorDescription } constructor should have the correct proxy."); }
public void ConstructorInitializesTheEndpointsWithOptions() { var options = new EventHubConnectionOptions { CustomEndpointAddress = new Uri("sb://iam.custom.net") }; var endpoint = new Uri("http://my.endpoint.com"); var credential = new Mock <EventHubTokenCredential>(Mock.Of <TokenCredential>()); var client = new AmqpClient(endpoint.Host, "somePath", credential.Object, options); Assert.That(client.ConnectionEndpoint.Host, Is.EqualTo(options.CustomEndpointAddress.Host), "The connection endpoint should have used the custom endpoint URI from the options."); Assert.That(client.ServiceEndpoint.Host, Is.EqualTo(endpoint.Host), "The service endpoint should have used the namespace URI."); }
public async Task ConnectionCanConnectToEventHubsUsingAnIdentityCredential() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { var options = new EventHubConnectionOptions(); var credential = EventHubsTestEnvironment.Instance.Credential; await using (var connection = new TestConnectionWithRetryPolicy(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, credential)) { Assert.That(() => connection.GetPropertiesAsync(), Throws.Nothing); } } }
public async Task ConnectionCanConnectToEventHubsUsingAnIdentityCredential() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { var options = new EventHubConnectionOptions(); var credential = new ClientSecretCredential(TestEnvironment.EventHubsTenant, TestEnvironment.EventHubsClient, TestEnvironment.EventHubsSecret); await using (var connection = new TestConnectionWithTransport(TestEnvironment.FullyQualifiedNamespace, scope.EventHubName, credential)) { Assert.That(() => connection.GetPropertiesAsync(), Throws.Nothing); } } }
internal override TransportClient CreateTransportClient(string fullyQualifiedNamespace, string eventHubName, EventHubTokenCredential credential, EventHubConnectionOptions options) { var client = new Mock <TransportClient>(); client .Setup(client => client.ServiceEndpoint) .Returns(new Uri($"amgp://{ fullyQualifiedNamespace }.com/{ eventHubName }")); return(client.Object); }
internal override TransportClient CreateTransportClient(string fullyQualifiedNamespace, string eventHubName, EventHubTokenCredential credential, EventHubConnectionOptions options) { var mockTransport = new Mock <TransportClient>(); mockTransport .Setup(t => t.ServiceEndpoint) .Returns(() => _serviceEndpoint); return(mockTransport.Object); }
public void ConnectionOptionsDefaultProxy() { #region Snippet:EventHubs_Sample02_ConnectionOptionsDefaultProxy var options = new EventHubConnectionOptions { TransportType = EventHubsTransportType.AmqpWebSockets, Proxy = HttpClient.DefaultProxy }; #endregion Assert.That(options, Is.Not.Null); }
public async Task ConnectionCanConnectToEventHubsUsingSharedAccessSignatureConnectionString() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { var options = new EventHubConnectionOptions(); var audience = EventHubConnection.BuildConnectionAudience(options.TransportType, EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName); var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringWithSharedAccessSignature(scope.EventHubName, audience); await using (var connection = new TestConnectionWithTransport(connectionString, options)) { Assert.That(() => connection.GetPropertiesAsync(), Throws.Nothing); } } }
/// <summary> /// Provides test cases for the constructor tests. /// </summary> /// public static IEnumerable <object[]> ConstructorClonesOptionsCases() { var fakeConnection = "Endpoint=sb://not-real.servicebus.windows.net/;SharedAccessKeyName=DummyKey;SharedAccessKey=[not_real];EntityPath=fake"; var options = new EventHubConnectionOptions { TransportType = TransportType.AmqpWebSockets, Proxy = Mock.Of <IWebProxy>() }; yield return(new object[] { new ReadableOptionsMock(fakeConnection, options), options, "connection string" }); yield return(new object[] { new ReadableOptionsMock("fullyQualifiedNamespace", "path", Mock.Of <TokenCredential>(), options), options, "expanded argument" }); }
public void CloneProducesACopy() { var options = new EventHubConnectionOptions { TransportType = EventHubsTransportType.AmqpWebSockets, Proxy = Mock.Of <IWebProxy>() }; EventHubConnectionOptions clone = options.Clone(); Assert.That(clone, Is.Not.Null, "The clone should not be null."); Assert.That(clone.TransportType, Is.EqualTo(options.TransportType), "The connection type of the clone should match."); Assert.That(clone.Proxy, Is.EqualTo(options.Proxy), "The proxy of the clone should match."); }
public void ContructorWithExpandedArgumentsCreatesTheTransportClient() { var fullyQualifiedNamespace = "my.eventhubs.com"; var path = "some-hub"; var keyName = "aWonderfulKey"; var key = "ABC4223"; var resource = $"amqps://{ fullyQualifiedNamespace }/{ path }"; var options = new EventHubConnectionOptions { TransportType = TransportType.AmqpTcp }; var signature = new SharedAccessSignature(resource, keyName, key); var client = new EventHubConnection(fullyQualifiedNamespace, path, new SharedAccessSignatureCredential(signature), options); Assert.That(GetTransportClient(client), Is.Not.Null); }
public async Task ConnectionCanConnectToEventHubsUsingSharedAccessSignatureConnectionString() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { var options = new EventHubConnectionOptions(); var audience = EventHubConnection.BuildConnectionAudience(options.TransportType, EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName); EventHubsTestEnvironment tempQualifier = EventHubsTestEnvironment.Instance; var signature = new SharedAccessSignature(audience, tempQualifier.SharedAccessKeyName, tempQualifier.SharedAccessKey, TimeSpan.FromMinutes(30)); var connectionString = $"Endpoint=sb://{tempQualifier.FullyQualifiedNamespace };EntityPath={ scope.EventHubName };SharedAccessSignature={ signature.Value }"; await using (var connection = new TestConnectionWithTransport(connectionString, options)) { Assert.That(() => connection.GetPropertiesAsync(), Throws.Nothing); } } }