Example #1
0
        public void ExecuteAsync_IfBlobHasChanged_NotifiesWatcherAndReturnsSuccessResult()
        {
            // Arrange
            string functionId = "FunctionId";
            string eTag       = TouchBlob(TestContainerName, TestBlobName);
            Mock <IBlobWrittenWatcher> mock = new Mock <IBlobWrittenWatcher>(MockBehavior.Strict);

            mock.Setup(w => w.Notify(It.IsAny <BlobWithContainer <BlobBaseClient> >()))
            .Verifiable();
            IBlobWrittenWatcher blobWrittenWatcher = mock.Object;

            BlobQueueTriggerExecutor product = CreateProductUnderTest(null, blobWrittenWatcher);

            BlobQueueRegistration registration = new BlobQueueRegistration
            {
                BlobServiceClient = _blobServiceClient,
                Executor          = CreateDummyTriggeredFunctionExecutor()
            };

            product.Register(functionId, registration);

            var message = CreateMessage(functionId, "OriginalETag");

            // Act
            Task <FunctionResult> task = product.ExecuteAsync(message, CancellationToken.None);

            // Assert
            task.WaitUntilCompleted();
            mock.Verify();
            Assert.True(task.Result.Succeeded);
        }
Example #2
0
        public void ExecuteAsync_IfBlobHasBeenDeleted_ReturnsSuccessResult()
        {
            // Arrange
            string functionId = "FunctionId";

            // by default, Blob doesn't exist in the fake account, so it's as if it were deleted.
            BlobQueueTriggerExecutor product = CreateProductUnderTest();

            BlobQueueRegistration registration = new BlobQueueRegistration
            {
                BlobServiceClient = _blobServiceClient,
                Executor          = CreateDummyTriggeredFunctionExecutor()
            };

            product.Register(functionId, registration);

            var message = CreateMessage(functionId, "OriginalETag");

            // Act
            Task <FunctionResult> task = product.ExecuteAsync(message, CancellationToken.None);

            // Assert
            Assert.True(task.Result.Succeeded);

            // Validate log is written
            var logMessage = _loggerProvider.GetAllLogMessages().Single();

            Assert.AreEqual("BlobNotFound", logMessage.EventId.Name);
            Assert.AreEqual(LogLevel.Debug, logMessage.Level);
            Assert.AreEqual(3, logMessage.State.Count());
            Assert.AreEqual(TestBlobName, logMessage.GetStateValue <string>("blobName"));
            Assert.AreEqual(TestQueueMessageId, logMessage.GetStateValue <string>("queueMessageId"));
            Assert.True(!string.IsNullOrWhiteSpace(logMessage.GetStateValue <string>("{OriginalFormat}")));
        }
Example #3
0
        public void ExecuteAsync_IfInnerExecutorFails_ReturnsFailureResult()
        {
            // Arrange
            string functionId   = "FunctionId";
            string matchingETag = TouchBlob(TestContainerName, TestBlobName);

            IBlobCausalityReader causalityReader = CreateStubCausalityReader();

            FunctionResult expectedResult          = new FunctionResult(false);
            Mock <ITriggeredFunctionExecutor> mock = new Mock <ITriggeredFunctionExecutor>(MockBehavior.Strict);

            mock.Setup(e => e.TryExecuteAsync(
                           It.IsAny <TriggeredFunctionData>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync(expectedResult)
            .Verifiable();

            BlobQueueTriggerExecutor product = CreateProductUnderTest(causalityReader);

            ITriggeredFunctionExecutor innerExecutor = mock.Object;
            BlobQueueRegistration      registration  = new BlobQueueRegistration
            {
                BlobServiceClient = _blobServiceClient,
                Executor          = innerExecutor
            };

            product.Register(functionId, registration);

            var message = CreateMessage(functionId, matchingETag);

            // Act
            Task <FunctionResult> task = product.ExecuteAsync(message, CancellationToken.None);

            // Assert
            Assert.False(task.Result.Succeeded);
        }
        public void ExecuteAsync_IfInnerExecutorFails_ReturnsFailureResult()
        {
            // Arrange
            string               functionId      = "FunctionId";
            string               matchingETag    = "ETag";
            IBlobETagReader      eTagReader      = CreateStubETagReader(matchingETag);
            IBlobCausalityReader causalityReader = CreateStubCausalityReader();

            FunctionResult expectedResult          = new FunctionResult(false);
            Mock <ITriggeredFunctionExecutor> mock = new Mock <ITriggeredFunctionExecutor>(MockBehavior.Strict);

            mock.Setup(e => e.TryExecuteAsync(
                           It.IsAny <TriggeredFunctionData>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync(expectedResult)
            .Verifiable();

            BlobQueueTriggerExecutor product = CreateProductUnderTest(eTagReader, causalityReader);

            ITriggeredFunctionExecutor innerExecutor = mock.Object;

            product.Register(functionId, innerExecutor);

            IStorageQueueMessage message = CreateMessage(functionId, matchingETag);

            // Act
            Task <FunctionResult> task = product.ExecuteAsync(message, CancellationToken.None);

            // Assert
            Assert.False(task.Result.Succeeded);
        }
        public void ExecuteAsync_IfBlobIsUnchanged_CallsInnerExecutor()
        {
            // Arrange
            string                   functionId       = "FunctionId";
            string                   matchingETag     = "ETag";
            Guid                     expectedParentId = Guid.NewGuid();
            IBlobETagReader          eTagReader       = CreateStubETagReader(matchingETag);
            IBlobCausalityReader     causalityReader  = CreateStubCausalityReader(expectedParentId);
            Mock <IFunctionExecutor> mock             = new Mock <IFunctionExecutor>(MockBehavior.Strict);

            mock.Setup(e => e.TryExecuteAsync(It.Is <IFunctionInstance>(f => f.ParentId == expectedParentId),
                                              It.IsAny <CancellationToken>()))
            .Returns(Task.FromResult <IDelayedException>(null))
            .Verifiable();
            IFunctionExecutor        innerExecutor = mock.Object;
            BlobQueueTriggerExecutor product       = CreateProductUnderTest(eTagReader, causalityReader, innerExecutor);

            product.Register(functionId, CreateFakeInstanceFactory());

            IStorageQueueMessage message = CreateMessage(functionId, matchingETag);

            // Act
            Task <bool> task = product.ExecuteAsync(message, CancellationToken.None);

            // Assert
            task.WaitUntilCompleted();
            mock.Verify();
        }
        public void ExecuteAsync_IfBlobHasChanged_NotifiesWatcherAndReturnsSuccessResult()
        {
            // Arrange
            string                     functionId = "FunctionId";
            IBlobETagReader            eTagReader = CreateStubETagReader("NewETag");
            Mock <IBlobWrittenWatcher> mock       = new Mock <IBlobWrittenWatcher>(MockBehavior.Strict);

            mock.Setup(w => w.Notify(It.IsAny <IStorageBlob>()))
            .Verifiable();
            IBlobWrittenWatcher      blobWrittenWatcher = mock.Object;
            BlobQueueTriggerExecutor product            = CreateProductUnderTest(eTagReader, blobWrittenWatcher);

            BlobQueueRegistration registration = new BlobQueueRegistration
            {
                BlobClient = CreateClient(),
                Executor   = CreateDummyTriggeredFunctionExecutor()
            };

            product.Register(functionId, registration);

            IStorageQueueMessage message = CreateMessage(functionId, "OriginalETag");

            // Act
            Task <FunctionResult> task = product.ExecuteAsync(message, CancellationToken.None);

            // Assert
            task.WaitUntilCompleted();
            mock.Verify();
            Assert.True(task.Result.Succeeded);
        }
        public void ExecuteAsync_IfBlobHasBeenDeleted_ReturnsSuccessResult()
        {
            // Arrange
            var    account    = new FakeAccount();
            string functionId = "FunctionId";

            // by default, Blob doesn't exist in the fake account, so it's as if it were deleted.
            BlobQueueTriggerExecutor product = CreateProductUnderTest();

            BlobQueueRegistration registration = new BlobQueueRegistration
            {
                BlobClient = account.CreateCloudBlobClient(),
                Executor   = CreateDummyTriggeredFunctionExecutor()
            };

            product.Register(functionId, registration);

            var message = CreateMessage(functionId, "OriginalETag");

            // Act
            Task <FunctionResult> task = product.ExecuteAsync(message, CancellationToken.None);

            // Assert
            Assert.True(task.Result.Succeeded);
        }
        public void ExecuteAsync_IfMessageIsFunctionIdIsRegistered_GetsETag(BlobType expectedBlobType)
        {
            // Arrange
            string expectedContainerName = "container";
            string expectedBlobName      = TestBlobName;
            string functionId            = "FunctionId";
            Mock <IBlobETagReader> mock  = new Mock <IBlobETagReader>(MockBehavior.Strict);

            mock.Setup(r => r.GetETagAsync(It.Is <IStorageBlob>(b => b.BlobType == (StorageBlobType)expectedBlobType &&
                                                                b.Name == expectedBlobName && b.Container.Name == expectedContainerName),
                                           It.IsAny <CancellationToken>()))
            .Returns(Task.FromResult("ETag"))
            .Verifiable();
            IBlobETagReader          eTagReader = mock.Object;
            BlobQueueTriggerExecutor product    = CreateProductUnderTest(eTagReader);

            product.Register(functionId, CreateDummyTriggeredFunctionExecutor());

            BlobTriggerMessage triggerMessage = new BlobTriggerMessage
            {
                FunctionId    = functionId,
                BlobType      = (StorageBlobType)expectedBlobType,
                ContainerName = expectedContainerName,
                BlobName      = expectedBlobName,
                ETag          = "OriginalETag"
            };
            IStorageQueueMessage message = CreateMessage(triggerMessage);

            // Act
            Task task = product.ExecuteAsync(message, CancellationToken.None);

            // Assert
            task.WaitUntilCompleted();
            mock.Verify();
        }
Example #9
0
        public void ExecuteAsync_IfMessageIsFunctionIdIsNotRegistered_ReturnsSuccessResult()
        {
            // Arrange
            BlobQueueTriggerExecutor product = CreateProductUnderTest();
            var message = CreateMessage(new BlobTriggerMessage {
                BlobName = TestBlobName, FunctionId = "Missing"
            });

            // Act
            Task <FunctionResult> task = product.ExecuteAsync(message, CancellationToken.None);

            // Assert
            Assert.True(task.Result.Succeeded);

            // Validate log is written
            var logMessage = _loggerProvider.GetAllLogMessages().Single();

            Assert.AreEqual("FunctionNotFound", logMessage.EventId.Name);
            Assert.AreEqual(LogLevel.Debug, logMessage.Level);
            Assert.AreEqual(4, logMessage.State.Count());
            Assert.AreEqual(TestBlobName, logMessage.GetStateValue <string>("blobName"));
            Assert.AreEqual("Missing", logMessage.GetStateValue <string>("functionName"));
            Assert.AreEqual(TestQueueMessageId, logMessage.GetStateValue <string>("queueMessageId"));
            Assert.True(!string.IsNullOrWhiteSpace(logMessage.GetStateValue <string>("{OriginalFormat}")));
        }
Example #10
0
        public void ExecuteAsync_IfMessageIsNotJson_Throws()
        {
            // Arrange
            BlobQueueTriggerExecutor product = CreateProductUnderTest();
            var message = CreateMessage("ThisIsNotValidJson");

            // Act
            Task task = product.ExecuteAsync(message, CancellationToken.None);

            // Assert
            Assert.Throws <JsonReaderException>(() => task.GetAwaiter().GetResult());
        }
Example #11
0
        public void ExecuteAsync_IfFunctionIdIsNull_Throws()
        {
            // Arrange
            BlobQueueTriggerExecutor product = CreateProductUnderTest();
            var message = CreateMessage("{}");

            // Act
            Task task = product.ExecuteAsync(message, CancellationToken.None);

            // Assert
            ExceptionAssert.ThrowsInvalidOperation(() => task.GetAwaiter().GetResult(), "Invalid function ID.");
        }
        public void ExecuteAsync_IfMessageIsJsonNull_Throws()
        {
            // Arrange
            BlobQueueTriggerExecutor product = CreateProductUnderTest();
            IStorageQueueMessage     message = CreateMessage("null");

            // Act
            Task task = product.ExecuteAsync(message, CancellationToken.None);

            // Assert
            ExceptionAssert.ThrowsInvalidOperation(() => task.GetAwaiter().GetResult(),
                                                   "Invalid blob trigger message.");
        }
        public void ExecuteAsync_IfMessageIsFunctionIdIsNotRegistered_ReturnsSuccessResult()
        {
            // Arrange
            BlobQueueTriggerExecutor product = CreateProductUnderTest();
            IStorageQueueMessage     message = CreateMessage(new BlobTriggerMessage {
                FunctionId = "Missing"
            });

            // Act
            Task <FunctionResult> task = product.ExecuteAsync(message, CancellationToken.None);

            // Assert
            Assert.True(task.Result.Succeeded);
        }
        public async Task ExecuteAsync_IfBlobIsUnchanged_CallsInnerExecutor()
        {
            // Arrange
            var    account          = new FakeAccount();
            string functionId       = "FunctionId";
            string matchingETag     = "ETag";
            Guid   expectedParentId = Guid.NewGuid();
            var    message          = CreateMessage(functionId, matchingETag);

            SetEtag(account, TestContainerName, TestBlobName, matchingETag);

            IBlobCausalityReader causalityReader = CreateStubCausalityReader(expectedParentId);

            FunctionResult expectedResult          = new FunctionResult(true);
            Mock <ITriggeredFunctionExecutor> mock = new Mock <ITriggeredFunctionExecutor>(MockBehavior.Strict);

            mock.Setup(e => e.TryExecuteAsync(It.IsAny <TriggeredFunctionData>(), It.IsAny <CancellationToken>()))
            .Callback <TriggeredFunctionData, CancellationToken>(
                (mockInput, mockCancellationToken) =>
            {
                Assert.Equal(expectedParentId, mockInput.ParentId);

                var resultBlob = (ICloudBlob)mockInput.TriggerValue;
                Assert.Equal(TestBlobName, resultBlob.Name);
            })
            .ReturnsAsync(expectedResult)
            .Verifiable();

            ITriggeredFunctionExecutor innerExecutor = mock.Object;
            BlobQueueTriggerExecutor   product       = CreateProductUnderTest(causalityReader);

            BlobQueueRegistration registration = new BlobQueueRegistration
            {
                BlobClient = account.CreateCloudBlobClient(),
                Executor   = innerExecutor
            };

            product.Register(functionId, registration);

            // Act
            FunctionResult result = await product.ExecuteAsync(message, CancellationToken.None);

            // Assert
            Assert.Same(expectedResult, result);
            mock.Verify();
        }
        public void ExecuteAsync_IfBlobHasBeenDeleted_ReturnsSuccessResult()
        {
            // Arrange
            string                   functionId = "FunctionId";
            IBlobETagReader          eTagReader = CreateStubETagReader(null);
            BlobQueueTriggerExecutor product    = CreateProductUnderTest(eTagReader);

            product.Register(functionId, CreateDummyTriggeredFunctionExecutor());

            IStorageQueueMessage message = CreateMessage(functionId, "OriginalETag");

            // Act
            Task <FunctionResult> task = product.ExecuteAsync(message, CancellationToken.None);

            // Assert
            Assert.True(task.Result.Succeeded);
        }
        public void ExecuteAsync_IfInnerExecutorFails_ReturnsFalse()
        {
            // Arrange
            string                   functionId      = "FunctionId";
            string                   matchingETag    = "ETag";
            IBlobETagReader          eTagReader      = CreateStubETagReader(matchingETag);
            IBlobCausalityReader     causalityReader = CreateStubCausalityReader();
            IFunctionExecutor        innerExecutor   = CreateStubInnerExecutor(CreateDummyDelayedException());
            BlobQueueTriggerExecutor product         = CreateProductUnderTest(eTagReader, causalityReader, innerExecutor);

            product.Register(functionId, CreateFakeInstanceFactory());

            IStorageQueueMessage message = CreateMessage(functionId, matchingETag);

            // Act
            Task <bool> task = product.ExecuteAsync(message, CancellationToken.None);

            // Assert
            Assert.False(task.Result);
        }
        public void ExecuteAsync_IfInnerExecutorSucceeds_ReturnsSuccessResult()
        {
            // Arrange
            var account = new FakeAccount();

            string functionId   = "FunctionId";
            string matchingETag = "ETag";

            SetEtag(account, TestContainerName, TestBlobName, matchingETag);

            IBlobCausalityReader causalityReader = CreateStubCausalityReader();

            FunctionResult expectedResult          = new FunctionResult(true);
            Mock <ITriggeredFunctionExecutor> mock = new Mock <ITriggeredFunctionExecutor>(MockBehavior.Strict);

            mock.Setup(e => e.TryExecuteAsync(
                           It.IsAny <TriggeredFunctionData>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync(expectedResult)
            .Verifiable();

            BlobQueueTriggerExecutor product = CreateProductUnderTest(causalityReader);

            ITriggeredFunctionExecutor innerExecutor = mock.Object;
            BlobQueueRegistration      registration  = new BlobQueueRegistration
            {
                BlobClient = account.CreateCloudBlobClient(),
                Executor   = innerExecutor
            };

            product.Register(functionId, registration);

            var message = CreateMessage(functionId, matchingETag);

            // Act
            Task <FunctionResult> task = product.ExecuteAsync(message, CancellationToken.None);

            // Assert
            Assert.Same(expectedResult, task.Result);
        }
        public async Task ExecuteAsync_IfBlobIsUnchanged_CallsInnerExecutor()
        {
            // Arrange
            string functionId                    = "FunctionId";
            string matchingETag                  = "ETag";
            Guid   expectedParentId              = Guid.NewGuid();
            IStorageQueueMessage message         = CreateMessage(functionId, matchingETag);
            IBlobETagReader      eTagReader      = CreateStubETagReader(matchingETag);
            IBlobCausalityReader causalityReader = CreateStubCausalityReader(expectedParentId);

            FunctionResult expectedResult          = new FunctionResult(true);
            Mock <ITriggeredFunctionExecutor> mock = new Mock <ITriggeredFunctionExecutor>(MockBehavior.Strict);

            mock.Setup(e => e.TryExecuteAsync(It.IsAny <TriggeredFunctionData>(), It.IsAny <CancellationToken>()))
            .Callback <TriggeredFunctionData, CancellationToken>(
                (mockInput, mockCancellationToken) =>
            {
                Assert.Equal(expectedParentId, mockInput.ParentId);

                StorageBlockBlob resultBlob = (StorageBlockBlob)mockInput.TriggerValue;
                Assert.Equal(TestBlobName, resultBlob.Name);
            })
            .ReturnsAsync(expectedResult)
            .Verifiable();

            ITriggeredFunctionExecutor innerExecutor = mock.Object;
            BlobQueueTriggerExecutor   product       = CreateProductUnderTest(eTagReader, causalityReader);

            product.Register(functionId, innerExecutor);

            // Act
            FunctionResult result = await product.ExecuteAsync(message, CancellationToken.None);

            // Assert
            Assert.Same(expectedResult, result);
            mock.Verify();
        }