From f8279122ac6fbec13001d9ddb40d0d58580a9b40 Mon Sep 17 00:00:00 2001 From: Vadim Kovalyov Date: Thu, 17 Dec 2020 11:43:06 -0800 Subject: [PATCH] Fix policy test flakiness (#4110) There was another issue in Policy tests that make them flaky. `LeafDevice.CreateAsync` appears to be not idempotent, so there is a race condition, when LeafDevice tries to connect before the policy is updated, and in case of failed authorization, it tries to delete and re-create the device. That screws up cached symmetric keys in EH. And since EH does not refresh the device scopes (and keys) more often that 2min, the test fails after several retries. The solution is to not to use `LeafDevice` - not to remove the device in case of authorization error, but just retry again. --- .../LeafDevice.cs | 1 - .../AuthorizationPolicy.cs | 47 ++++++++++--------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/test/Microsoft.Azure.Devices.Edge.Test.Common/LeafDevice.cs b/test/Microsoft.Azure.Devices.Edge.Test.Common/LeafDevice.cs index 444634048a8..b7be7f8e9e6 100644 --- a/test/Microsoft.Azure.Devices.Edge.Test.Common/LeafDevice.cs +++ b/test/Microsoft.Azure.Devices.Edge.Test.Common/LeafDevice.cs @@ -8,7 +8,6 @@ namespace Microsoft.Azure.Devices.Edge.Test.Common using System.IO; using System.Linq; using System.Net; - using System.Reflection.Metadata.Ecma335; using System.Security.Cryptography.X509Certificates; using System.Text; using System.Threading; diff --git a/test/Microsoft.Azure.Devices.Edge.Test/AuthorizationPolicy.cs b/test/Microsoft.Azure.Devices.Edge.Test/AuthorizationPolicy.cs index 3105c032d36..420d63f84ad 100644 --- a/test/Microsoft.Azure.Devices.Edge.Test/AuthorizationPolicy.cs +++ b/test/Microsoft.Azure.Devices.Edge.Test/AuthorizationPolicy.cs @@ -3,8 +3,10 @@ namespace Microsoft.Azure.Devices.Edge.Test { using System; using System.Collections.Generic; + using System.Net; using System.Threading; using System.Threading.Tasks; + using Microsoft.Azure.Devices.Client; using Microsoft.Azure.Devices.Client.Exceptions; using Microsoft.Azure.Devices.Edge.Test.Common; using Microsoft.Azure.Devices.Edge.Test.Common.Certs; @@ -135,38 +137,37 @@ await edgeHub.WaitForReportedPropertyUpdatesAsync( }, token); + // Create device manually. We can't use LeafDevice.CreateAsync() since it is not + // idempotent and cannot be retried reliably. + Devices.Device edge = await this.iotHub.GetDeviceIdentityAsync(this.runtime.DeviceId, token); + Devices.Device leaf = new Devices.Device(deviceId2) + { + Authentication = new AuthenticationMechanism + { + Type = AuthenticationType.Sas + }, + Scope = edge.Scope + }; + + leaf = await this.iotHub.CreateDeviceIdentityAsync(leaf, token); + string connectionString = + $"HostName={this.iotHub.Hostname};" + + $"DeviceId={leaf.Id};" + + $"SharedAccessKey={leaf.Authentication.SymmetricKey.PrimaryKey};" + + $"GatewayHostName={Dns.GetHostName().ToLower()}"; + // There is no reliable way to signal when the policy // is updated in $edgehub, so need to retry several times. // // DefaultProgressive => 55 sec max. - LeafDevice leaf = null; await RetryPolicy.DefaultProgressive.ExecuteAsync( async () => { - leaf = await LeafDevice.CreateAsync( - deviceId2, - Protocol.Mqtt, - AuthenticationType.Sas, - Option.Some(this.runtime.DeviceId), - false, - CertificateAuthority.GetQuickstart(), - this.iotHub, - token, - Option.None()); + using var client = DeviceClient.CreateFromConnectionString(connectionString); + await client.OpenAsync(); }, token); - // verify device is authorized after policy update. - await TryFinally.DoAsync( - async () => - { - DateTime seekTime = DateTime.Now; - await leaf.SendEventAsync(token); - await leaf.WaitForEventsReceivedAsync(seekTime, token); - }, - async () => - { - await leaf.DeleteIdentityAsync(token); - }); + await this.iotHub.DeleteDeviceIdentityAsync(leaf, token); } ///