Exemple #1
0
        public void TestFails()
        {
            foreach (var method in this.GetType().GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static))
            {
                Mock <IExtensionRegistry> extensionsMock = new Mock <IExtensionRegistry>(MockBehavior.Strict);
                extensionsMock.Setup(p => p.GetExtensions(typeof(IExtensionConfigProvider))).Returns(Enumerable.Empty <object>());
                extensionsMock.Setup(p => p.GetExtensions(typeof(ITriggerBindingProvider))).Returns(Enumerable.Empty <object>());
                extensionsMock.Setup(p => p.GetExtensions(typeof(IBindingProvider))).Returns(Enumerable.Empty <object>());
                extensionsMock.Setup(p => p.GetExtensions(typeof(IArgumentBindingProvider <>))).Returns(Enumerable.Empty <object>());
                Mock <IFunctionExecutor> executorMock = new Mock <IFunctionExecutor>(MockBehavior.Strict);

                IFunctionIndexCollector stubIndex = new Mock <IFunctionIndexCollector>().Object;

                FunctionIndexer indexer = new FunctionIndexer(
                    new Mock <ITriggerBindingProvider>(MockBehavior.Strict).Object,
                    new Mock <IBindingProvider>(MockBehavior.Strict).Object,
                    new Mock <IJobActivator>(MockBehavior.Strict).Object,
                    executorMock.Object,
                    extensionsMock.Object,
                    new SingletonManager(),
                    new TestTraceWriter(TraceLevel.Verbose),
                    null);

                Assert.Throws <FunctionIndexingException>(() => indexer.IndexMethodAsync(method, stubIndex, CancellationToken.None).GetAwaiter().GetResult());
            }
        }
Exemple #2
0
        private void RunOnFunctionTimeoutTest(bool isDebugging, string expectedMessage)
        {
            System.Timers.Timer timer = new System.Timers.Timer(TimeSpan.FromMinutes(1).TotalMilliseconds);
            timer.Start();

            Assert.True(timer.Enabled);
            Assert.False(_cancellationTokenSource.IsCancellationRequested);

            MethodInfo       method    = typeof(Functions).GetMethod("MethodLevel", BindingFlags.Static | BindingFlags.Public);
            TimeoutAttribute attribute = method.GetCustomAttribute <TimeoutAttribute>();

            _descriptor = FunctionIndexer.FromMethod(method);
            Guid instanceId            = Guid.Parse("B2D1DD72-80E2-412B-A22E-3B4558F378B4");
            bool timeoutWhileDebugging = false;

            TestLogger logger = new TestLogger("Tests.FunctionExecutor");

            FunctionExecutor.OnFunctionTimeout(timer, _descriptor, instanceId, attribute.Timeout, timeoutWhileDebugging, logger, _cancellationTokenSource, () => isDebugging);

            Assert.False(timer.Enabled);
            Assert.NotEqual(isDebugging, _cancellationTokenSource.IsCancellationRequested);

            string message = string.Format("Timeout value of 00:01:00 exceeded by function 'Functions.MethodLevel' (Id: 'b2d1dd72-80e2-412b-a22e-3b4558f378b4'). {0}", expectedMessage);

            // verify ILogger
            LogMessage log = logger.LogMessages.Single();

            Assert.Equal(LogLevel.Error, log.Level);
            Assert.Equal(message, log.FormattedMessage);
        }
        public async Task GetHostIdAsync_NoJobMethodsFound_ReturnsExpectedResult()
        {
            // pick a type that returns no job methods
            var type           = typeof(FunctionNameAttribute);
            var firstJobMethod = FunctionIndexer.GetJobMethods(type).FirstOrDefault();

            Assert.Null(firstJobMethod);

            var mockTypeLocator = new Mock <ITypeLocator>(MockBehavior.Strict);

            mockTypeLocator.Setup(p => p.GetTypes()).Returns(new Type[] { type });
            var idProvider = new DefaultHostIdProvider(mockTypeLocator.Object);

            // as long as this test assembly name stays the same, the ID
            // computed should remain static. If this test is failing
            // it likely means we've changed the ID computation algorithm
            // which would be a BREAKING CHANGE
            string expected = "943b1888c56ce8f0c96b2e66e1c74a7e";

            var id = await idProvider.GetHostIdAsync(CancellationToken.None);

            Assert.Equal(expected, id);

            // ensure the same ID is returned each time
            mockTypeLocator = new Mock <ITypeLocator>(MockBehavior.Strict);
            mockTypeLocator.Setup(p => p.GetTypes()).Returns(new Type[] { type });
            idProvider = new DefaultHostIdProvider(mockTypeLocator.Object);
            Assert.Equal(expected, await idProvider.GetHostIdAsync(CancellationToken.None));
        }
        // Helper to do the indexing.
        private static Tuple <FunctionDescriptor, IFunctionDefinition> IndexMethod(string methodName, INameResolver nameResolver = null)
        {
            MethodInfo method = typeof(FunctionIndexerIntegrationTests).GetMethod(methodName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);

            Assert.NotNull(method);

            FunctionIndexer indexer = FunctionIndexerFactory.Create(CloudStorageAccount.DevelopmentStorageAccount,
                                                                    nameResolver);

            Tuple <FunctionDescriptor, IFunctionDefinition> indexEntry = null;
            Mock <IFunctionIndexCollector> indexMock = new Mock <IFunctionIndexCollector>(MockBehavior.Strict);

            indexMock
            .Setup((i) => i.Add(
                       It.IsAny <IFunctionDefinition>(),
                       It.IsAny <FunctionDescriptor>(),
                       It.IsAny <MethodInfo>()))
            .Callback <IFunctionDefinition, FunctionDescriptor, MethodInfo>(
                (ifd, fd, i) => indexEntry = Tuple.Create(fd, ifd));
            IFunctionIndexCollector index = indexMock.Object;

            indexer.IndexMethodAsync(method, index, CancellationToken.None).GetAwaiter().GetResult();

            return(indexEntry);
        }
Exemple #5
0
        public async Task IndexMethod_IfMethodReturnsAsyncVoid_Throws()
        {
            var traceWriter    = new TestTraceWriter(TraceLevel.Verbose);
            var loggerFactory  = new LoggerFactory();
            var loggerProvider = new TestLoggerProvider();

            loggerFactory.AddProvider(loggerProvider);

            // Arrange
            IFunctionIndexCollector index   = CreateStubFunctionIndex();
            FunctionIndexer         product = CreateProductUnderTest(traceWriter: traceWriter, loggerFactory: loggerFactory);

            // Act & Assert
            await product.IndexMethodAsync(typeof(FunctionIndexerTests).GetMethod("ReturnAsyncVoid"), index, CancellationToken.None);

            string expectedMessage = "Function 'ReturnAsyncVoid' is async but does not return a Task. Your function may not run correctly.";

            // Validate TraceWriter
            var traceWarning = traceWriter.Traces.First(p => p.Level == TraceLevel.Warning);

            Assert.Equal(expectedMessage, traceWarning.Message);

            // Validate Logger
            var logger        = loggerProvider.CreatedLoggers.Single(l => l.Category == Logging.LogCategories.Startup);
            var loggerWarning = logger.LogMessages.Single();

            Assert.Equal(LogLevel.Warning, loggerWarning.Level);
            Assert.Equal(expectedMessage, loggerWarning.FormattedMessage);
        }
        public async Task GetHostIdAsync_ReturnsExpectedResult()
        {
            // ensure that the below job method is discovered and this test
            // assembly is used to generate the ID
            var type           = GetType();
            var firstJobMethod = FunctionIndexer.GetJobMethods(type).FirstOrDefault();

            Assert.NotNull(firstJobMethod);

            var mockTypeLocator = new Mock <ITypeLocator>(MockBehavior.Strict);

            mockTypeLocator.Setup(p => p.GetTypes()).Returns(new Type[] { type });
            var idProvider = new DefaultHostIdProvider(mockTypeLocator.Object);

            // as long as this test assembly name stays the same, the ID
            // computed should remain static. If this test is failing
            // it likely means we've changed the ID computation algorithm
            // which would be a BREAKING CHANGE
            string expected = "be6b3849f12290e0f182b27aa6f10fff";

            var id = await idProvider.GetHostIdAsync(CancellationToken.None);

            Assert.Equal(expected, id);

            // ensure the same ID is returned each time
            mockTypeLocator = new Mock <ITypeLocator>(MockBehavior.Strict);
            mockTypeLocator.Setup(p => p.GetTypes()).Returns(new Type[] { type });
            idProvider = new DefaultHostIdProvider(mockTypeLocator.Object);
            Assert.Equal(expected, await idProvider.GetHostIdAsync(CancellationToken.None));

            // ensure once the ID is computed, a cached result is returned
            Assert.Equal(expected, await idProvider.GetHostIdAsync(CancellationToken.None));
            Assert.Equal(expected, await idProvider.GetHostIdAsync(CancellationToken.None));
            mockTypeLocator.Verify(p => p.GetTypes(), Times.Once);
        }
Exemple #7
0
 public void FormatLockId_ReturnsExpectedValue(SingletonScope scope, string scopeId, string expectedLockId)
 {
     MethodInfo methodInfo = this.GetType().GetMethod("TestJob", BindingFlags.Static | BindingFlags.NonPublic);
     var descriptor = FunctionIndexer.FromMethod(methodInfo);
     string actualLockId = SingletonManager.FormatLockId(descriptor, scope, "TestHostId", scopeId);
     Assert.Equal(expectedLockId, actualLockId);
 }
        private IFunctionInstance CreateFunctionInstance(Guid id)
        {
            var method     = GetType().GetMethod(nameof(TestFunction), BindingFlags.NonPublic | BindingFlags.Static);
            var descriptor = FunctionIndexer.FromMethod(method);

            return(new FunctionInstance(id, null, new ExecutionReason(), null, null, descriptor));
        }
        private string ComputeHostId()
        {
            // Search through all types for the first job method.
            // The reason we have to do this rather than attempt to use the entry assembly
            // (Assembly.GetEntryAssembly) is because that doesn't work for WebApps, and the
            // SDK supports both WebApp and Console app hosts.
            MethodInfo firstJobMethod = null;

            foreach (var type in _typeLocator.GetTypes())
            {
                firstJobMethod = FunctionIndexer.GetJobMethods(type).FirstOrDefault();
                if (firstJobMethod != null)
                {
                    break;
                }
            }

            // Compute hash and map to Guid
            // If the job host doesn't yet have any job methods (e.g. it's a new project)
            // then a default ID is generated
            string hostName = firstJobMethod?.DeclaringType.Assembly.FullName ?? "Unknown";
            Guid   id;

            using (var md5 = MD5.Create())
            {
                var hash = md5.ComputeHash(Encoding.UTF8.GetBytes(hostName));
                id = new Guid(hash);
            }

            return(id.ToString("N"));
        }
        public void IsJobMethod_ReturnsFalse_IfMethodHasNoParameters()
        {
            // Act
            bool actual = FunctionIndexer.IsJobMethod(typeof(FunctionIndexerTests).GetMethod("MethodWithNoParameters"));

            // Verify
            Assert.Equal(false, actual);
        }
        public void IsJobMethod_ReturnsTrue_IfMethodHasJobAttributeButNoParameters()
        {
            // Act
            bool actual = FunctionIndexer.IsJobMethod(typeof(FunctionIndexerTests).GetMethod("MethodWithJobAttributeButNoParameters"));

            // Verify
            Assert.Equal(true, actual);
        }
        public void IsJobMethod_ReturnsTrue_IfMethodHasJobParameterAttributes_FromExtensionAssemblies()
        {
            // Act
            bool actual = FunctionIndexer.IsJobMethod(typeof(FunctionIndexerTests).GetMethod("MethodWithExtensionJobParameterAttributes"));

            // Verify
            Assert.Equal(true, actual);
        }
        public void IsJobMethod_ReturnsFalse_IfMethodHasNoSdkAttributes()
        {
            // Act
            bool actual = FunctionIndexer.IsJobMethod(typeof(FunctionIndexerTests).GetMethod("MethodWithUnboundOutParameterAndNoJobAttribute"));

            // Verify
            Assert.Equal(false, actual);
        }
Exemple #14
0
        public void GetListenerSingletonOrNull_ReturnsListenerClassSingleton()
        {
            MethodInfo method = this.GetType().GetMethod("TestJob", BindingFlags.Static | BindingFlags.NonPublic);
            var descriptor = FunctionIndexer.FromMethod(method);

            SingletonAttribute attribute = SingletonManager.GetListenerSingletonOrNull(typeof(TestListener), descriptor);
            Assert.Equal("Listener", attribute.ScopeId);
        }
Exemple #15
0
 public void Dispose()
 {
     if (_currentBatch.Any())
     {
         FunctionIndexer.IndexAsync(_currentBatch).Wait();
         _currentBatch.Clear();
     }
 }
        public void IndexMethod_IfMethodReturnsVoid_DoesNotThrow()
        {
            // Arrange
            IFunctionIndexCollector index   = CreateStubFunctionIndex();
            FunctionIndexer         product = CreateProductUnderTest();

            // Act & Assert
            product.IndexMethodAsync(typeof(FunctionIndexerTests).GetMethod("ReturnVoid"),
                                     index, CancellationToken.None).GetAwaiter().GetResult();
        }
        public SingletonValueProviderTests()
        {
            _attribute = new SingletonAttribute("TestScope");
            SingletonManager singletonManager = new SingletonManager(null, null, null, null, null, new FixedHostIdProvider(TestHostId));
            var method = GetType().GetMethod("TestJob", BindingFlags.Static | BindingFlags.Public);

            _method        = FunctionIndexer.FromMethod(method);
            _lockId        = SingletonManager.FormatLockId(_method, SingletonScope.Function, TestHostId, _attribute.ScopeId);
            _valueProvider = new SingletonValueProvider(_method, "TestScope", TestInstanceId, _attribute, singletonManager);
        }
        public void IsJobMethod_ReturnsFalse_IfMethodHasUnresolvedGenericParameter()
        {
            // Arrange
            Mock <IFunctionIndex> indexMock = new Mock <IFunctionIndex>();

            // Act
            bool actual = FunctionIndexer.IsJobMethod(typeof(FunctionIndexerTests).GetMethod("MethodWithGenericParameter"));

            // Verify
            Assert.Equal(false, actual);
        }
Exemple #19
0
        public void GetListenerSingletonOrNull_ThrowsOnMultiple()
        {
            MethodInfo method = this.GetType().GetMethod("TestJob_MultipleListenerSingletons", BindingFlags.Static | BindingFlags.NonPublic);
            var descriptor = FunctionIndexer.FromMethod(method);

            NotSupportedException exception = Assert.Throws<NotSupportedException>(() =>
            {
                SingletonManager.GetListenerSingletonOrNull(typeof(TestListener), descriptor);
            });
            Assert.Equal("Only one SingletonAttribute using mode 'Listener' is allowed.", exception.Message);
        }
        public void IndexMethod_IgnoresMethod_IfNonJobMethod(string method)
        {
            // Arrange
            Mock <IFunctionIndexCollector> indexMock = new Mock <IFunctionIndexCollector>();
            FunctionIndexer product = CreateProductUnderTest();

            // Act
            product.IndexMethodAsync(typeof(FunctionIndexerTests).GetMethod(method), indexMock.Object, CancellationToken.None).GetAwaiter().GetResult();

            // Verify
            indexMock.Verify(i => i.Add(It.IsAny <IFunctionDefinition>(), It.IsAny <FunctionDescriptor>(), It.IsAny <MethodInfo>()), Times.Never);
        }
        public void IsJobMethod_ReturnsFalse_IfMethodHasNoSdkAttributes()
        {
            // Arrange
            Mock <IFunctionIndex> indexMock = new Mock <IFunctionIndex>();
            FunctionIndexer       product   = CreateProductUnderTest();

            // Act
            bool actual = product.IsJobMethod(typeof(FunctionIndexerTests).GetMethod("MethodWithUnboundOutParameterAndNoJobAttribute"));

            // Verify
            Assert.Equal(false, actual);
        }
        public void IsJobMethod_ReturnsTrue_IfMethodHasJobParameterAttributes()
        {
            // Arrange
            Mock <IFunctionIndex> indexMock = new Mock <IFunctionIndex>();
            FunctionIndexer       product   = CreateProductUnderTest();

            // Act
            bool actual = product.IsJobMethod(typeof(FunctionIndexerTests).GetMethod("MethodWithJobParameterAttributes"));

            // Verify
            Assert.Equal(true, actual);
        }
Exemple #23
0
        public void GetFunctionTimeout_ReturnsExpected()
        {
            // Arrange
            var             collector = new TestIndexCollector();
            FunctionIndexer product   = CreateProductUnderTest();

            // Act & Assert
            product.IndexMethodAsync(typeof(FunctionIndexerTests).GetMethod("Timeout_Set"),
                                     collector, CancellationToken.None).GetAwaiter().GetResult();

            Assert.Equal(TimeSpan.FromMinutes(30), collector.Functions.First().TimeoutAttribute.Timeout);
        }
Exemple #24
0
        public void GetFunctionTraceLevel_ReturnsExpectedLevel(string method, TraceLevel level)
        {
            // Arrange
            var             collector = new TestIndexCollector();
            FunctionIndexer product   = CreateProductUnderTest();

            // Act & Assert
            product.IndexMethodAsync(typeof(FunctionIndexerTests).GetMethod(method),
                                     collector, CancellationToken.None).GetAwaiter().GetResult();

            Assert.Equal(level, collector.Functions.First().TraceLevel);
        }
 public void TestFails()
 {
     foreach (var method in this.GetType().GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static))
     {
         IFunctionIndexCollector stubIndex = new Mock <IFunctionIndexCollector>().Object;
         FunctionIndexer         indexer   = new FunctionIndexer(
             new Mock <ITriggerBindingProvider>(MockBehavior.Strict).Object,
             new Mock <IBindingProvider>(MockBehavior.Strict).Object,
             new Mock <IJobActivator>(MockBehavior.Strict).Object);
         Assert.Throws <FunctionIndexingException>(() => indexer.IndexMethodAsync(method, stubIndex, CancellationToken.None).GetAwaiter().GetResult());
     }
 }
        public void IsSdkMethod_ReturnsFalse_IfMethodHasNoParameters()
        {
            // Arrange
            Mock <IFunctionIndex> indexMock = new Mock <IFunctionIndex>();
            FunctionIndexer       product   = CreateProductUnderTest();

            // Act
            bool actual = product.IsSdkMethod(typeof(FunctionIndexerTests).GetMethod("MethodWithNoParameters"));

            // Verify
            Assert.Equal(false, actual);
        }
        private async Task<IFunctionIndex> CreateAsync(CancellationToken cancellationToken)
        {
            FunctionIndex index = new FunctionIndex();
            FunctionIndexer indexer = new FunctionIndexer(_triggerBindingProvider, _bindingProvider, _activator, _executor, _extensions);
            IReadOnlyList<Type> types = _typeLocator.GetTypes();

            foreach (Type type in types)
            {
                await indexer.IndexTypeAsync(type, index, cancellationToken);
            }

            return index;
        }
        public static void AddParameterModels(string parameterName, FunctionInstanceArgument argument, ParameterLog log,
                                              FunctionInstanceSnapshot snapshot, ICollection <ParamModel> parameterModels)
        {
            ParamModel model = new ParamModel
            {
                Name            = parameterName,
                ArgInvokeString = argument.Value
            };

            if (log != null)
            {
                model.Status = Format(log);
            }

            if (argument.IsBlob)
            {
                model.ExtendedBlobModel = LogAnalysis.CreateExtendedBlobModel(snapshot, argument);
            }

            parameterModels.Add(model);

            // Special-case IBinder, which adds sub-parameters.
            BinderParameterLog binderLog = log as BinderParameterLog;

            if (binderLog != null)
            {
                IEnumerable <BinderParameterLogItem> items = binderLog.Items;

                if (items != null)
                {
                    int count = items.Count();
                    model.Status = String.Format(CultureInfo.CurrentCulture, "Bound {0} object{1}.", count, count != 1 ? "s" : String.Empty);

                    foreach (BinderParameterLogItem item in items)
                    {
                        if (item == null)
                        {
                            continue;
                        }

                        ParameterSnapshot        itemSnapshot = HostIndexer.CreateParameterSnapshot(item.Descriptor);
                        string                   itemName     = parameterName + ": " + itemSnapshot.AttributeText;
                        FunctionInstanceArgument itemArgument =
                            FunctionIndexer.CreateFunctionInstanceArgument(item.Value, item.Descriptor);

                        AddParameterModels(itemName, itemArgument, item.Log, snapshot, parameterModels);
                    }
                }
            }
        }
        public void IndexMethod_IfMethodReturnsTaskOfTResult_Throws()
        {
            // Arrange
            IFunctionIndexCollector index   = CreateDummyFunctionIndex();
            FunctionIndexer         product = CreateProductUnderTest();

            // Act & Assert
            FunctionIndexingException exception = Assert.Throws <FunctionIndexingException>(
                () => product.IndexMethodAsync(typeof(FunctionIndexerTests).GetMethod("ReturnGenericTask"), index,
                                               CancellationToken.None).GetAwaiter().GetResult());
            InvalidOperationException innerException = exception.InnerException as InvalidOperationException;

            Assert.NotNull(innerException);
            Assert.Equal("Functions must return Task or void.", innerException.Message);
        }
Exemple #30
0
        public async Task IndexMethod_IfMethodReturnsAsyncVoid_Throws()
        {
            var traceWriter = new TestTraceWriter(TraceLevel.Verbose);

            // Arrange
            IFunctionIndexCollector index   = CreateStubFunctionIndex();
            FunctionIndexer         product = CreateProductUnderTest(traceWriter: traceWriter);

            // Act & Assert
            await product.IndexMethodAsync(typeof(FunctionIndexerTests).GetMethod("ReturnAsyncVoid"), index, CancellationToken.None);

            var warning = traceWriter.Traces.First(p => p.Level == TraceLevel.Warning);

            Assert.Equal("Function 'ReturnAsyncVoid' is async but does not return a Task. Your function may not run correctly.", warning.Message);
        }
        public void IsJobMethod_ReturnsTrue_IfMethodHasJobParameterAttributes_FromExtensionAssemblies()
        {
            // Arrange
            Mock <IFunctionIndex> indexMock  = new Mock <IFunctionIndex>();
            IExtensionRegistry    extensions = new DefaultExtensionRegistry();

            extensions.RegisterExtension <ITriggerBindingProvider>(new TestExtensionTriggerBindingProvider());
            extensions.RegisterExtension <IBindingProvider>(new TestExtensionBindingProvider());
            FunctionIndexer product = FunctionIndexerFactory.Create(extensionRegistry: extensions);

            // Act
            bool actual = product.IsJobMethod(typeof(FunctionIndexerTests).GetMethod("MethodWithExtensionJobParameterAttributes"));

            // Verify
            Assert.Equal(true, actual);
        }
        public void TestFails()
        {
            foreach (var method in this.GetType().GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static))
            {
                Mock<IExtensionRegistry> extensionsMock = new Mock<IExtensionRegistry>(MockBehavior.Strict);
                extensionsMock.Setup(p => p.GetExtensions(typeof(ITriggerBindingProvider))).Returns(Enumerable.Empty<object>());
                extensionsMock.Setup(p => p.GetExtensions(typeof(IBindingProvider))).Returns(Enumerable.Empty<object>());
                Mock<IFunctionExecutor> executorMock = new Mock<IFunctionExecutor>(MockBehavior.Strict);

                IFunctionIndexCollector stubIndex = new Mock<IFunctionIndexCollector>().Object;
                FunctionIndexer indexer = new FunctionIndexer(
                    new Mock<ITriggerBindingProvider>(MockBehavior.Strict).Object,
                    new Mock<IBindingProvider>(MockBehavior.Strict).Object,
                    new Mock<IJobActivator>(MockBehavior.Strict).Object,
                    executorMock.Object,
                    extensionsMock.Object);

                Assert.Throws<FunctionIndexingException>(() => indexer.IndexMethodAsync(method, stubIndex, CancellationToken.None).GetAwaiter().GetResult());
            }
        }