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()); } }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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()); } }