private async Task ReuseAuthenticationMethod_SingleDevice(Client.TransportType transport) { TestDevice testDevice = await TestDevice.GetTestDeviceAsync(Logger, _devicePrefix).ConfigureAwait(false); var authenticationMethod = new DeviceAuthenticationSasToken(testDevice.ConnectionString, disposeWithClient: false); // Create an instance of the device client, send a test message and then close and dispose it. DeviceClient deviceClient = DeviceClient.Create(testDevice.IoTHubHostName, authenticationMethod, transport); using var message1 = new Client.Message(); await deviceClient.SendEventAsync(message1).ConfigureAwait(false); await deviceClient.CloseAsync(); deviceClient.Dispose(); Logger.Trace("Test with instance 1 completed"); // Perform the same steps again, reusing the previously created authentication method instance to ensure // that the sdk did not dispose the user supplied authentication method instance. DeviceClient deviceClient2 = DeviceClient.Create(testDevice.IoTHubHostName, authenticationMethod, transport); using var message2 = new Client.Message(); await deviceClient2.SendEventAsync(message2).ConfigureAwait(false); await deviceClient2.CloseAsync(); deviceClient2.Dispose(); Logger.Trace("Test with instance 2 completed, reused the previously created authentication method instance for the device client."); authenticationMethod.Dispose(); }
private async Task AuthenticationMethodDisposesTokenRefresher(Client.TransportType transport) { TestDevice testDevice = await TestDevice.GetTestDeviceAsync(Logger, _devicePrefix).ConfigureAwait(false); var authenticationMethod = new DeviceAuthenticationSasToken(testDevice.ConnectionString, disposeWithClient: true); // Create an instance of the device client, send a test message and then close and dispose it. DeviceClient deviceClient = DeviceClient.Create(testDevice.IoTHubHostName, authenticationMethod, transport); using var message1 = new Client.Message(); await deviceClient.SendEventAsync(message1).ConfigureAwait(false); await deviceClient.CloseAsync(); deviceClient.Dispose(); Logger.Trace("Test with instance 1 completed"); // Perform the same steps again, reusing the previously created authentication method instance. // Since the default behavior is to dispose AuthenticationWithTokenRefresh authentication method on DeviceClient disposal, // this should now throw an ObjectDisposedException. DeviceClient deviceClient2 = DeviceClient.Create(testDevice.IoTHubHostName, authenticationMethod, transport); using var message2 = new Client.Message(); Func <Task> act = async() => await deviceClient2.SendEventAsync(message2).ConfigureAwait(false); await act.Should().ThrowAsync <ObjectDisposedException>(); }
private async Task ReuseAuthenticationMethod_MuxedDevices(Client.TransportType transport, int devicesCount) { IList <TestDevice> testDevices = new List <TestDevice>(); IList <DeviceClient> deviceClients = new List <DeviceClient>(); IList <AuthenticationWithTokenRefresh> authenticationMethods = new List <AuthenticationWithTokenRefresh>(); IList <AmqpConnectionStatusChange> amqpConnectionStatuses = new List <AmqpConnectionStatusChange>(); // Set up amqp transport settings to multiplex all device sessions over the same amqp connection. var amqpTransportSettings = new AmqpTransportSettings(transport) { AmqpConnectionPoolSettings = new AmqpConnectionPoolSettings { Pooling = true, MaxPoolSize = 1, }, }; for (int i = 0; i < devicesCount; i++) { TestDevice testDevice = await TestDevice.GetTestDeviceAsync(Logger, _devicePrefix).ConfigureAwait(false); #pragma warning disable CA2000 // Dispose objects before losing scope - the authentication method is disposed at the end of the test. var authenticationMethod = new DeviceAuthenticationSasToken(testDevice.ConnectionString, disposeWithClient: false); #pragma warning restore CA2000 // Dispose objects before losing scope testDevices.Add(testDevice); authenticationMethods.Add(authenticationMethod); } // Initialize the client instances, set the connection status change handler and open the connection. for (int i = 0; i < devicesCount; i++) { #pragma warning disable CA2000 // Dispose objects before losing scope - the client instance is disposed during the course of the test. DeviceClient deviceClient = DeviceClient.Create(testDevices[i].IoTHubHostName, authenticationMethods[i], new ITransportSettings[] { amqpTransportSettings }); #pragma warning restore CA2000 // Dispose objects before losing scope var amqpConnectionStatusChange = new AmqpConnectionStatusChange(testDevices[i].Id, Logger); deviceClient.SetConnectionStatusChangesHandler(amqpConnectionStatusChange.ConnectionStatusChangesHandler); amqpConnectionStatuses.Add(amqpConnectionStatusChange); await deviceClient.OpenAsync().ConfigureAwait(false); deviceClients.Add(deviceClient); } // Close and dispose client instance 1. // The closed client should report a status of "disabled" while the rest of them should be connected. // This is to ensure that disposal on one multiplexed device doesn't cause cascading failures // in the rest of the devices on the same tcp connection. await deviceClients[0].CloseAsync().ConfigureAwait(false); deviceClients[0].Dispose(); amqpConnectionStatuses[0].LastConnectionStatus.Should().Be(ConnectionStatus.Disabled); Logger.Trace($"{nameof(ReuseAuthenticationMethod_MuxedDevices)}: Confirming the rest of the multiplexed devices are online and operational."); bool notRecovered = true; var sw = Stopwatch.StartNew(); while (notRecovered && sw.Elapsed < MaxWaitTime) { notRecovered = false; for (int i = 1; i < devicesCount; i++) { if (amqpConnectionStatuses[i].LastConnectionStatus != ConnectionStatus.Connected) { await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false); notRecovered = true; break; } } } notRecovered.Should().BeFalse(); // Send a message through the rest of the multiplexed client instances. var message = new Client.Message(); for (int i = 1; i < devicesCount; i++) { await deviceClients[i].SendEventAsync(message).ConfigureAwait(false); Logger.Trace($"Test with client {i} completed."); } message.Dispose(); // Close and dispose all of the client instances. for (int i = 1; i < devicesCount; i++) { await deviceClients[i].CloseAsync().ConfigureAwait(false); deviceClients[i].Dispose(); } deviceClients.Clear(); amqpConnectionStatuses.Clear(); // Initialize the client instances by reusing the created authentication methods and open the connection. for (int i = 0; i < devicesCount; i++) { #pragma warning disable CA2000 // Dispose objects before losing scope - the client instance is disposed at the end of the test. DeviceClient deviceClient = DeviceClient.Create(testDevices[i].IoTHubHostName, authenticationMethods[i], new ITransportSettings[] { amqpTransportSettings }); #pragma warning restore CA2000 // Dispose objects before losing scope var amqpConnectionStatusChange = new AmqpConnectionStatusChange(testDevices[i].Id, Logger); deviceClient.SetConnectionStatusChangesHandler(amqpConnectionStatusChange.ConnectionStatusChangesHandler); amqpConnectionStatuses.Add(amqpConnectionStatusChange); await deviceClient.OpenAsync().ConfigureAwait(false); deviceClients.Add(deviceClient); } // Ensure that all clients are connected successfully, and the close and dispose the instances. // Also dispose the authentication methods created. for (int i = 0; i < devicesCount; i++) { amqpConnectionStatuses[i].LastConnectionStatus.Should().Be(ConnectionStatus.Connected); await deviceClients[i].CloseAsync(); deviceClients[i].Dispose(); authenticationMethods[i].Dispose(); amqpConnectionStatuses[i].LastConnectionStatus.Should().Be(ConnectionStatus.Disabled); } }