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_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());
        }
Beispiel #3
0
        public void GetMonitor_ReturnsSharedMonitor()
        {
            var queueListener           = new QueueListener();
            var watcherMock             = new Mock <IBlobWrittenWatcher>(MockBehavior.Strict);
            var executor                = new BlobQueueTriggerExecutor(watcherMock.Object, NullLogger <BlobListener> .Instance);
            var sharedBlobQueueListener = new SharedBlobQueueListener(queueListener, executor);
            var sharedListenerMock      = new Mock <ISharedListener>(MockBehavior.Strict);
            var blobListener1           = new BlobListener(sharedBlobQueueListener);
            var blobListener2           = new BlobListener(sharedBlobQueueListener);

            var monitor1 = blobListener1.GetMonitor();
            var monitor2 = blobListener1.GetMonitor();

            Assert.AreSame(monitor1, monitor2);
            Assert.AreSame(monitor1, queueListener);
        }
        public async Task ExecuteAsync_IfBlobIsUnchanged_CallsInnerExecutor()
        {
            // Arrange
            string functionId       = "FunctionId";
            Guid   expectedParentId = Guid.NewGuid();

            string matchingETag = TouchBlob(TestContainerName, TestBlobName);
            var    message      = CreateMessage(functionId, 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.AreEqual(expectedParentId, mockInput.ParentId);

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

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

            BlobQueueRegistration registration = new BlobQueueRegistration
            {
                BlobServiceClient = _blobServiceClient,
                Executor          = innerExecutor
            };

            product.Register(functionId, registration);

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

            // Assert
            Assert.AreSame(expectedResult, result);
            mock.Verify();
        }
        public SharedBlobQueueListener Create()
        {
            BlobQueueTriggerExecutor triggerExecutor = new BlobQueueTriggerExecutor(_blobWrittenWatcher, _loggerFactory.CreateLogger <BlobListener>());

            // The poison queue to use for a given poison blob lives in the same
            // storage account as the triggering blob by default. In multi-storage account scenarios
            // that means that we'll be writing to different poison queues, determined by
            // the triggering blob.
            // However we use a poison queue in the host storage account as a fallback default
            // in case a particular blob lives in a restricted "blob only" storage account (i.e. no queues).
            var defaultPoisonQueue = _hostQueueServiceClient.GetQueueClient(HostQueueNames.BlobTriggerPoisonQueue);

            // This special queue bypasses the QueueProcessorFactory - we don't want people to override this.
            // So we define our own custom queue processor factory for this listener
            var queuesOptions  = BlobsOptionsToQueuesOptions(_blobsOptions);
            var queueProcessor = new SharedBlobQueueProcessor(triggerExecutor, _hostBlobTriggerQueue, defaultPoisonQueue, _loggerFactory, queuesOptions);

            QueueListener.RegisterSharedWatcherWithQueueProcessor(queueProcessor, _sharedQueueWatcher);
            IListener listener = new QueueListener(_hostBlobTriggerQueue, defaultPoisonQueue, triggerExecutor, _exceptionHandler, _loggerFactory,
                                                   _sharedQueueWatcher, queuesOptions, queueProcessor, _functionDescriptor, functionId: SharedBlobQueueListenerFunctionId);

            return(new SharedBlobQueueListener(listener, triggerExecutor));
        }
 public SharedBlobQueueProcessor(BlobQueueTriggerExecutor triggerExecutor, QueueClient queue, QueueClient poisonQueue, ILoggerFactory loggerFactory, QueuesOptions queuesOptions)
     : base(new QueueProcessorOptions(queue, loggerFactory, queuesOptions, poisonQueue))
 {
     _executor = triggerExecutor;
 }
Beispiel #7
0
 public SharedBlobQueueListener(IListener listener, BlobQueueTriggerExecutor executor)
 {
     _listener = listener;
     _executor = executor;
 }