public void TestThrowsIfContainerDoesNotExist() { using var provider = new TestingAzureBlobLeaseDistributedLockProvider(); provider.Strategy.ContainerName = "does-not-exist"; var @lock = provider.CreateLock(nameof(TestThrowsIfContainerDoesNotExist)); Assert.Throws <RequestFailedException>(() => @lock.TryAcquire()?.Dispose()) .ErrorCode.ShouldEqual("ContainerNotFound"); }
public async Task TestSuccessfulRenewal() { using var provider = new TestingAzureBlobLeaseDistributedLockProvider(); provider.Strategy.Options = o => o.RenewalCadence(TimeSpan.FromSeconds(.05)); var @lock = provider.CreateLock(nameof(TestSuccessfulRenewal)); using var handle = @lock.Acquire(); await Task.Delay(TimeSpan.FromSeconds(.2)); // long enough for renewal to run Assert.DoesNotThrow(handle.Dispose); // observes the result of the renewal task }
public void TestExitsDespiteLongSleepTime() { using var provider = new TestingAzureBlobLeaseDistributedLockProvider(); provider.Strategy.Options = o => o.BusyWaitSleepTime(TimeSpan.FromSeconds(30), TimeSpan.FromMinutes(1)); var @lock = provider.CreateLock(nameof(TestExitsDespiteLongSleepTime)); using var handle1 = @lock.Acquire(); var handle2Task = @lock.TryAcquireAsync(TimeSpan.FromSeconds(2)).AsTask(); Assert.IsFalse(handle2Task.Wait(TimeSpan.FromSeconds(.05))); handle1.Dispose(); Assert.IsTrue(handle2Task.Wait(TimeSpan.FromSeconds(5))); }
[NonParallelizable, Retry(tryCount: 3)] // timing-sensitive public void TestTriggersHandleLostIfLeaseExpiresNaturally() { using var provider = new TestingAzureBlobLeaseDistributedLockProvider(); provider.Strategy.Options = o => o.RenewalCadence(Timeout.InfiniteTimeSpan).Duration(TimeSpan.FromSeconds(15)); var @lock = provider.CreateLock(nameof(TestTriggersHandleLostIfLeaseExpiresNaturally)); using var handle = @lock.Acquire(); using var @event = new ManualResetEventSlim(initialState: false); using var registration = handle.HandleLostToken.Register(@event.Set); using var faultingRegistration = handle.HandleLostToken.Register(() => throw new TimeZoneNotFoundException()); Assert.IsTrue(@event.Wait(TimeSpan.FromSeconds(15.1))); Assert.Throws <RequestFailedException>(handle.Dispose) .ErrorCode.ShouldEqual("LeaseLost"); }
public async Task TestLockOnDifferentBlobClientTypes( [Values] BlobClientType type, [Values] bool isAsync) { if (isAsync) { await TestAsync(); } else { SyncViaAsync.Run(_ => TestAsync(), default(object)); } async ValueTask TestAsync() { using var provider = new TestingAzureBlobLeaseDistributedLockProvider(); var name = provider.GetUniqueSafeName(); var client = CreateClient(type, name); if (client is AppendBlobClient appendClient) { Assert.That( Assert.Throws <RequestFailedException>(() => appendClient.CreateIfNotExists()).ToString(), Does.Contain("This feature is not currently supported by the Storage Emulator") ); return; } if (client.GetType() == typeof(BlobBaseClient)) { // work around inability to do CreateIfNotExists for the base client new BlobClient(AzureCredentials.ConnectionString, AzureCredentials.DefaultBlobContainerName, name).Upload(Stream.Null); } var @lock = new AzureBlobLeaseDistributedLock(client); await using var handle = await @lock.TryAcquireAsync(); Assert.IsNotNull(handle); await using var nestedHandle = await @lock.TryAcquireAsync(); Assert.IsNull(nestedHandle); } }
public void TestCanUseLeaseIdForBlobOperations() { using var provider = new TestingAzureBlobLeaseDistributedLockProvider(); var name = provider.GetUniqueSafeName(); var client = new PageBlobClient(AzureCredentials.ConnectionString, AzureCredentials.DefaultBlobContainerName, name); const int BlobSize = 512; client.Create(size: BlobSize); var @lock = new AzureBlobLeaseDistributedLock(client); using var handle = @lock.Acquire(); Assert.Throws <RequestFailedException>(() => client.UploadPages(new MemoryStream(new byte[BlobSize]), offset: 0)) .ErrorCode.ShouldEqual(AzureErrors.LeaseIdMissing); Assert.DoesNotThrow( () => client.UploadPages(new MemoryStream(new byte[BlobSize]), offset: 0, conditions: new PageBlobRequestConditions { LeaseId = handle.LeaseId }) ); handle.Dispose(); Assert.Throws <ObjectDisposedException>(() => handle.LeaseId.ToString()); }
public async Task TestWrapperCreateIfNotExists([Values] BlobClientType type) { using var provider = new TestingAzureBlobLeaseDistributedLockProvider(); var name = provider.GetUniqueSafeName(); var client = CreateClient(type, name); var wrapper = new BlobClientWrapper(client); var metadata = new Dictionary <string, string> { ["abc"] = "123" }; if (client is AppendBlobClient) { Assert.That( Assert.ThrowsAsync <RequestFailedException>(async() => await wrapper.CreateIfNotExistsAsync(metadata, CancellationToken.None)).ToString(), Does.Contain("This feature is not currently supported by the Storage Emulator") ); return; } if (client.GetType() == typeof(BlobBaseClient)) { Assert.That( Assert.ThrowsAsync <InvalidOperationException>(async() => await wrapper.CreateIfNotExistsAsync(metadata, CancellationToken.None)).ToString(), Does.Contain("Either ensure that the blob exists or use a non-base client type") ); return; } await wrapper.CreateIfNotExistsAsync(metadata, CancellationToken.None); Assert.IsTrue((await client.ExistsAsync()).Value); CollectionAssert.AreEqual(metadata, (await client.GetPropertiesAsync()).Value.Metadata); Assert.DoesNotThrowAsync(async() => await wrapper.CreateIfNotExistsAsync(metadata, CancellationToken.None)); Assert.IsTrue((await client.ExistsAsync()).Value); }
public void TestCanAcquireIfContainerLeased() { using var provider = new TestingAzureBlobLeaseDistributedLockProvider(); provider.Strategy.ContainerName = "leased-container" + TargetFramework.Current.Replace('.', '-'); var containerClient = new BlobContainerClient(AzureCredentials.ConnectionString, provider.Strategy.ContainerName); var containerLeaseClient = new BlobLeaseClient(containerClient); try { containerClient.CreateIfNotExists(); containerLeaseClient.Acquire(TimeSpan.FromSeconds(60)); var @lock = provider.CreateLock(nameof(TestCanAcquireIfContainerLeased)); using var handle = @lock.TryAcquire(); Assert.IsNotNull(handle); } finally { try { containerLeaseClient.Release(); } finally { containerClient.DeleteIfExists(); } } }