public async Task Dispose_ReleasesBlobLease()
        {
            string hostId           = Guid.NewGuid().ToString();
            string instanceId       = Guid.NewGuid().ToString();
            string connectionString = AmbientConnectionStringProvider.Instance.GetConnectionString(ConnectionStringNames.Storage);

            var traceWriter = new TestTraceWriter(System.Diagnostics.TraceLevel.Verbose);

            using (var manager = await BlobLeaseManager.CreateAsync(connectionString, TimeSpan.FromSeconds(15), hostId, instanceId, traceWriter))
            {
                await TestHelpers.Await(() => manager.HasLease);
            }

            ICloudBlob blob = await GetLockBlobAsync(connectionString, hostId);

            string leaseId = null;

            try
            {
                // Acquire a lease on the host lock blob
                leaseId = await blob.AcquireLeaseAsync(TimeSpan.FromSeconds(15));

                await blob.ReleaseLeaseAsync(new AccessCondition { LeaseId = leaseId });
            }
            catch (StorageException exc) when(exc.RequestInformation.HttpStatusCode == 409)
            {
            }

            Assert.False(string.IsNullOrEmpty(leaseId), "Failed to acquire a blob lease. The lease was not properly released.");

            await ClearLeaseBlob(hostId);
        }
        public async Task HasLease_WhenLeaseIsAcquired_ReturnsTrue()
        {
            string connectionString = AmbientConnectionStringProvider.Instance.GetConnectionString(ConnectionStringNames.Storage);
            string hostId           = Guid.NewGuid().ToString();
            string instanceId       = Guid.NewGuid().ToString();
            var    traceWriter      = new TestTraceWriter(System.Diagnostics.TraceLevel.Verbose);

            using (var manager = await BlobLeaseManager.CreateAsync(connectionString, TimeSpan.FromSeconds(15), hostId, instanceId, traceWriter))
            {
                await TestHelpers.Await(() => manager.HasLease);

                Assert.Equal(instanceId, manager.LeaseId);
            }

            await ClearLeaseBlob(hostId);
        }
        public async Task DifferentHosts_UsingSameStorageAccount_CanObtainLease()
        {
            string hostId1          = Guid.NewGuid().ToString();
            string hostId2          = Guid.NewGuid().ToString();
            string instanceId       = Guid.NewGuid().ToString();
            string connectionString = AmbientConnectionStringProvider.Instance.GetConnectionString(ConnectionStringNames.Storage);
            var    traceWriter      = new TestTraceWriter(TraceLevel.Verbose);

            using (var manager1 = await BlobLeaseManager.CreateAsync(connectionString, TimeSpan.FromSeconds(15), hostId1, instanceId, traceWriter))
                using (var manager2 = await BlobLeaseManager.CreateAsync(connectionString, TimeSpan.FromSeconds(15), hostId2, instanceId, traceWriter))
                {
                    Task manager1Check = TestHelpers.Await(() => manager1.HasLease);
                    Task manager2Check = TestHelpers.Await(() => manager2.HasLease);

                    await Task.WhenAll(manager1Check, manager2Check);
                }

            await Task.WhenAll(ClearLeaseBlob(hostId1), ClearLeaseBlob(hostId2));
        }
        public async Task HasLeaseChanged_WhenLeaseIsAcquiredAndStateChanges_IsFired()
        {
            string hostId      = Guid.NewGuid().ToString();
            string instanceId  = Guid.NewGuid().ToString();
            var    traceWriter = new TestTraceWriter(TraceLevel.Verbose);
            var    resetEvent  = new ManualResetEventSlim();

            string     connectionString = AmbientConnectionStringProvider.Instance.GetConnectionString(ConnectionStringNames.Storage);
            ICloudBlob blob             = await GetLockBlobAsync(connectionString, hostId);

            // Acquire a lease on the host lock blob
            string leaseId = await blob.AcquireLeaseAsync(TimeSpan.FromSeconds(15));

            BlobLeaseManager manager = null;

            try
            {
                manager = await BlobLeaseManager.CreateAsync(connectionString, TimeSpan.FromSeconds(15), hostId, instanceId, traceWriter);

                manager.HasLeaseChanged += (s, a) => resetEvent.Set();
            }
            finally
            {
                await blob.ReleaseLeaseAsync(new AccessCondition { LeaseId = leaseId });
            }

            resetEvent.Wait(TimeSpan.FromSeconds(15));
            bool   hasLease      = manager.HasLease;
            string actualLeaseId = manager.LeaseId;

            manager.Dispose();

            Assert.True(resetEvent.IsSet);
            Assert.True(hasLease, $"{nameof(BlobLeaseManager.HasLease)} was not correctly set to 'true' when lease was acquired.");
            Assert.Equal(instanceId, actualLeaseId);

            await ClearLeaseBlob(hostId);
        }