public void ExecuteAsync_IfLeasedReceiptBecameCompleted_ReleasesLeaseAndReturnsSuccessResult() { // Arrange BlobTriggerExecutorContext context = CreateExecutorContext(); IBlobPathSource input = CreateBlobPath(context.Blob); Mock <IBlobReceiptManager> mock = CreateReceiptManagerReferenceMock(); int calls = 0; mock.Setup(m => m.TryReadAsync(It.IsAny <BlockBlobClient>(), It.IsAny <CancellationToken>())) .Returns(() => { int call = calls++; return(Task.FromResult(call == 0 ? BlobReceipt.Incomplete : BlobReceipt.Complete)); }); mock.Setup(m => m.TryAcquireLeaseAsync(It.IsAny <BlockBlobClient>(), It.IsAny <CancellationToken>())) .Returns(Task.FromResult("LeaseId")); mock.Setup(m => m.ReleaseLeaseAsync(It.IsAny <BlockBlobClient>(), It.IsAny <string>(), It.IsAny <CancellationToken>())) .Returns(Task.FromResult(0)) .Verifiable(); IBlobReceiptManager receiptManager = mock.Object; ITriggerExecutor <BlobTriggerExecutorContext> product = CreateProductUnderTest(input, receiptManager); // Act Task <FunctionResult> task = product.ExecuteAsync(context, CancellationToken.None); // Assert task.WaitUntilCompleted(); mock.Verify(); Assert.True(task.Result.Succeeded); }
public void ExecuteAsync_IfBlobDoesNotExist_ReturnsSuccessfulResult() { // Arrange BlobTriggerExecutorContext context = CreateExecutorContext(createBlob: false); IBlobPathSource input = CreateBlobPath(context.Blob); ITriggerExecutor <BlobTriggerExecutorContext> product = CreateProductUnderTest(input); // Act Task <FunctionResult> task = product.ExecuteAsync(context, CancellationToken.None); // Assert Assert.True(task.Result.Succeeded); // Validate log is written var logMessage = _loggerProvider.GetAllLogMessages().Single(); Assert.Equal("BlobHasNoETag", logMessage.EventId.Name); Assert.Equal(LogLevel.Debug, logMessage.Level); Assert.Equal(5, logMessage.State.Count()); Assert.Equal(context.Blob.BlobClient.Name, logMessage.GetStateValue <string>("blobName")); Assert.Equal("FunctionIdLogName", logMessage.GetStateValue <string>("functionName")); Assert.Equal(context.PollId, logMessage.GetStateValue <string>("pollId")); Assert.Equal(context.TriggerSource, logMessage.GetStateValue <BlobTriggerSource>("triggerSource")); Assert.True(!string.IsNullOrWhiteSpace(logMessage.GetStateValue <string>("{OriginalFormat}"))); }
public void ExecuteAsync_IfTryAcquireLeaseSucceeds_ReadsLatestReceipt() { // Arrange BlobTriggerExecutorContext context = CreateExecutorContext(); IBlobPathSource input = CreateBlobPath(context.Blob); Mock <IBlobReceiptManager> mock = CreateReceiptManagerReferenceMock(); int calls = 0; mock.Setup(m => m.TryReadAsync(It.IsAny <BlockBlobClient>(), It.IsAny <CancellationToken>())) .Returns(() => { return(Task.FromResult(calls++ == 0 ? BlobReceipt.Incomplete : BlobReceipt.Complete)); }); mock.Setup(m => m.TryAcquireLeaseAsync(It.IsAny <BlockBlobClient>(), It.IsAny <CancellationToken>())) .Returns(Task.FromResult("LeaseId")); mock.Setup(m => m.ReleaseLeaseAsync(It.IsAny <BlockBlobClient>(), It.IsAny <string>(), It.IsAny <CancellationToken>())) .Returns(Task.FromResult(0)); IBlobReceiptManager receiptManager = mock.Object; ITriggerExecutor <BlobTriggerExecutorContext> product = CreateProductUnderTest(input, receiptManager); // Act Task <FunctionResult> task = product.ExecuteAsync(context, CancellationToken.None); // Assert task.GetAwaiter().GetResult(); Assert.Equal(2, calls); }
public void ExecuteAsync_IfTryCreateReceiptSucceeds_TriesToAcquireLease() { // Arrange BlobTriggerExecutorContext context = CreateExecutorContext(); IBlobPathSource input = CreateBlobPath(context.Blob); Mock <IBlobReceiptManager> mock = CreateReceiptManagerReferenceMock(); mock.Setup(m => m.TryReadAsync(It.IsAny <BlockBlobClient>(), It.IsAny <CancellationToken>())) .Returns(Task.FromResult <BlobReceipt>(null)); mock.Setup(m => m.TryCreateAsync(It.IsAny <BlockBlobClient>(), It.IsAny <CancellationToken>())) .Returns(Task.FromResult(true)); mock.Setup(m => m.TryAcquireLeaseAsync(It.IsAny <BlockBlobClient>(), It.IsAny <CancellationToken>())) .Returns(Task.FromResult <string>(null)) .Verifiable(); IBlobReceiptManager receiptManager = mock.Object; ITriggerExecutor <BlobTriggerExecutorContext> product = CreateProductUnderTest(input, receiptManager); // Act Task <FunctionResult> task = product.ExecuteAsync(context, CancellationToken.None); // Assert task.GetAwaiter().GetResult(); mock.Verify(); }
public void ExecuteAsync_IfCompletedBlobReceiptExists_ReturnsSuccessfulResult() { // Arrange BlobTriggerExecutorContext context = CreateExecutorContext(); IBlobPathSource input = CreateBlobPath(context.Blob); string expectedETag = context.Blob.BlobClient.GetProperties().Value.ETag.ToString(); IBlobReceiptManager receiptManager = CreateCompletedReceiptManager(); ITriggerExecutor <BlobTriggerExecutorContext> product = CreateProductUnderTest(input, receiptManager); // Act Task <FunctionResult> task = product.ExecuteAsync(context, CancellationToken.None); // Assert Assert.True(task.Result.Succeeded); // Validate log is written var logMessage = _loggerProvider.GetAllLogMessages().Single(); Assert.Equal("BlobAlreadyProcessed", logMessage.EventId.Name); Assert.Equal(LogLevel.Debug, logMessage.Level); Assert.Equal(6, logMessage.State.Count()); Assert.Equal("FunctionIdLogName", logMessage.GetStateValue <string>("functionName")); Assert.Equal(context.Blob.BlobClient.Name, logMessage.GetStateValue <string>("blobName")); Assert.Equal(expectedETag, logMessage.GetStateValue <string>("eTag")); Assert.Equal(context.PollId, logMessage.GetStateValue <string>("pollId")); Assert.Equal(context.TriggerSource, logMessage.GetStateValue <BlobTriggerSource>("triggerSource")); Assert.True(!string.IsNullOrWhiteSpace(logMessage.GetStateValue <string>("{OriginalFormat}"))); }
public void ExecuteAsync_IfEnqueueAsyncThrows_ReleasesLease() { // Arrange BlobTriggerExecutorContext context = CreateExecutorContext(); IBlobPathSource input = CreateBlobPath(context.Blob); InvalidOperationException expectedException = new InvalidOperationException(); Mock <IBlobReceiptManager> mock = CreateReceiptManagerReferenceMock(); mock.Setup(m => m.TryReadAsync(It.IsAny <BlockBlobClient>(), It.IsAny <CancellationToken>())) .Returns(Task.FromResult(BlobReceipt.Incomplete)); mock.Setup(m => m.TryAcquireLeaseAsync(It.IsAny <BlockBlobClient>(), It.IsAny <CancellationToken>())) .Returns(Task.FromResult("LeaseId")); mock.Setup(m => m.ReleaseLeaseAsync(It.IsAny <BlockBlobClient>(), It.IsAny <string>(), It.IsAny <CancellationToken>())) .Returns(Task.FromResult(0)) .Verifiable(); IBlobReceiptManager receiptManager = mock.Object; Mock <IBlobTriggerQueueWriter> queueWriterMock = new Mock <IBlobTriggerQueueWriter>(MockBehavior.Strict); queueWriterMock .Setup(w => w.EnqueueAsync(It.IsAny <BlobTriggerMessage>(), It.IsAny <CancellationToken>())) .Throws(expectedException); IBlobTriggerQueueWriter queueWriter = queueWriterMock.Object; ITriggerExecutor <BlobTriggerExecutorContext> product = CreateProductUnderTest(input, receiptManager, queueWriter); // Act Task <FunctionResult> task = product.ExecuteAsync(context, CancellationToken.None); // Assert task.WaitUntilCompleted(); mock.Verify(); InvalidOperationException exception = Assert.Throws <InvalidOperationException>( () => task.GetAwaiter().GetResult()); Assert.Same(expectedException, exception); }
public void ExecuteAsync_IfBlobDoesNotMatchPattern_ReturnsSuccessfulResult() { // Arrange var client = account.CreateBlobServiceClient(); string containerName = ContainerName; var container = client.GetBlobContainerClient(containerName); var otherContainer = client.GetBlobContainerClient("other"); IBlobPathSource input = BlobPathSource.Create(containerName + "/{name}"); ITriggerExecutor <BlobTriggerExecutorContext> product = CreateProductUnderTest(input); // Note: this test does not set the PollId. This ensures that we work okay with null values for these. var blob = otherContainer.GetBlockBlobClient("nonmatch"); var context = new BlobTriggerExecutorContext { Blob = new BlobWithContainer <BlobBaseClient>(otherContainer, blob), TriggerSource = BlobTriggerSource.ContainerScan }; // Act Task <FunctionResult> task = product.ExecuteAsync(context, CancellationToken.None); // Assert Assert.True(task.Result.Succeeded); // Validate log is written var logMessage = _loggerProvider.GetAllLogMessages().Single(); Assert.Equal("BlobDoesNotMatchPattern", logMessage.EventId.Name); Assert.Equal(LogLevel.Debug, logMessage.Level); Assert.Equal(6, logMessage.State.Count()); Assert.Equal("FunctionIdLogName", logMessage.GetStateValue <string>("functionName")); Assert.Equal(containerName + "/{name}", logMessage.GetStateValue <string>("pattern")); Assert.Equal(blob.Name, logMessage.GetStateValue <string>("blobName")); Assert.Null(logMessage.GetStateValue <string>("pollId")); Assert.Equal(context.TriggerSource, logMessage.GetStateValue <BlobTriggerSource>("triggerSource")); Assert.True(!string.IsNullOrWhiteSpace(logMessage.GetStateValue <string>("{OriginalFormat}"))); }
public void ExecuteAsync_IfTryAcquireLeaseFails_ReturnsFailureResult() { // Arrange BlobTriggerExecutorContext context = CreateExecutorContext(); IBlobPathSource input = CreateBlobPath(context.Blob); Mock <IBlobReceiptManager> mock = CreateReceiptManagerReferenceMock(); mock.Setup(m => m.TryReadAsync(It.IsAny <BlockBlobClient>(), It.IsAny <CancellationToken>())) .Returns(Task.FromResult(BlobReceipt.Incomplete)); mock.Setup(m => m.TryAcquireLeaseAsync(It.IsAny <BlockBlobClient>(), It.IsAny <CancellationToken>())) .Returns(Task.FromResult <string>(null)); IBlobReceiptManager receiptManager = mock.Object; ITriggerExecutor <BlobTriggerExecutorContext> product = CreateProductUnderTest(input, receiptManager); // Act Task <FunctionResult> task = product.ExecuteAsync(context, CancellationToken.None); // Assert Assert.False(task.Result.Succeeded); }
public void ExecuteAsync_IfLeasedIncompleteReceipt_EnqueuesMessageMarksCompletedReleasesLeaseAndReturnsSuccessResult() { // Arrange string expectedFunctionId = "FunctionId"; BlobTriggerExecutorContext context = CreateExecutorContext(); string expectedETag = context.Blob.BlobClient.GetProperties().Value.ETag.ToString(); IBlobPathSource input = CreateBlobPath(context.Blob); Mock <IBlobReceiptManager> managerMock = CreateReceiptManagerReferenceMock(); managerMock .Setup(m => m.TryReadAsync(It.IsAny <BlockBlobClient>(), It.IsAny <CancellationToken>())) .Returns(Task.FromResult(BlobReceipt.Incomplete)); managerMock .Setup(m => m.TryAcquireLeaseAsync(It.IsAny <BlockBlobClient>(), It.IsAny <CancellationToken>())) .Returns(Task.FromResult("LeaseId")); managerMock .Setup(m => m.MarkCompletedAsync(It.IsAny <BlockBlobClient>(), It.IsAny <string>(), It.IsAny <CancellationToken>())) .Returns(Task.FromResult(0)) .Verifiable(); managerMock .Setup(m => m.ReleaseLeaseAsync(It.IsAny <BlockBlobClient>(), It.IsAny <string>(), It.IsAny <CancellationToken>())) .Returns(Task.FromResult(0)) .Verifiable(); IBlobReceiptManager receiptManager = managerMock.Object; Mock <IBlobTriggerQueueWriter> queueWriterMock = new Mock <IBlobTriggerQueueWriter>(MockBehavior.Strict); queueWriterMock .Setup(w => w.EnqueueAsync(It.IsAny <BlobTriggerMessage>(), It.IsAny <CancellationToken>())) .Returns(Task.FromResult(("testQueueName", "testMessageId"))); IBlobTriggerQueueWriter queueWriter = queueWriterMock.Object; ITriggerExecutor <BlobTriggerExecutorContext> product = CreateProductUnderTest(expectedFunctionId, input, receiptManager, queueWriter); // Act Task <FunctionResult> task = product.ExecuteAsync(context, CancellationToken.None); // Assert task.WaitUntilCompleted(); queueWriterMock .Verify( w => w.EnqueueAsync(It.Is <BlobTriggerMessage>(m => m != null && m.FunctionId == expectedFunctionId /*&& m.BlobType == StorageBlobType.BlockBlob $$$ */ && m.BlobName == context.Blob.BlobClient.Name && m.ContainerName == context.Blob.BlobClient.BlobContainerName && m.ETag == expectedETag), It.IsAny <CancellationToken>()), Times.Once()); managerMock.Verify(); Assert.True(task.Result.Succeeded); // Validate log is written var logMessage = _loggerProvider.GetAllLogMessages().Single(); Assert.Equal("BlobMessageEnqueued", logMessage.EventId.Name); Assert.Equal(LogLevel.Debug, logMessage.Level); Assert.Equal(7, logMessage.State.Count()); Assert.Equal("FunctionIdLogName", logMessage.GetStateValue <string>("functionName")); Assert.Equal(context.Blob.BlobClient.Name, logMessage.GetStateValue <string>("blobName")); Assert.Equal("testQueueName", logMessage.GetStateValue <string>("queueName")); Assert.Equal("testMessageId", logMessage.GetStateValue <string>("messageId")); Assert.Equal(context.PollId, logMessage.GetStateValue <string>("pollId")); Assert.Equal(context.TriggerSource, logMessage.GetStateValue <BlobTriggerSource>("triggerSource")); Assert.True(!string.IsNullOrWhiteSpace(logMessage.GetStateValue <string>("{OriginalFormat}"))); }