private bool AreExpectedMetricsGenerated(TestMetricsLogger metricsLogger)
 {
     return(metricsLogger.EventsBegan.Contains(MetricEventNames.SpecializationSpecializeHost) && metricsLogger.EventsEnded.Contains(MetricEventNames.SpecializationSpecializeHost) &&
            metricsLogger.EventsBegan.Contains(MetricEventNames.SpecializationLanguageWorkerChannelManagerSpecialize) && metricsLogger.EventsEnded.Contains(MetricEventNames.SpecializationLanguageWorkerChannelManagerSpecialize) &&
            metricsLogger.EventsBegan.Contains(MetricEventNames.SpecializationRestartHost) && metricsLogger.EventsEnded.Contains(MetricEventNames.SpecializationRestartHost) &&
            metricsLogger.EventsBegan.Contains(MetricEventNames.SpecializationDelayUntilHostReady) && metricsLogger.EventsEnded.Contains(MetricEventNames.SpecializationDelayUntilHostReady));
 }
        public void ShouldEnforceSequentialRestart_WithCorrectConfig(string value, bool expectedResult)
        {
            var metricsLogger = new TestMetricsLogger();

            _host.Setup(h => h.StartAsync(It.IsAny <CancellationToken>()))
            .Returns(Task.CompletedTask);

            var hostBuilder = new Mock <IScriptHostBuilder>();

            hostBuilder.Setup(b => b.BuildHost(It.IsAny <bool>(), It.IsAny <bool>()))
            .Returns(_host.Object);

            IConfiguration config = new ConfigurationBuilder()
                                    .AddInMemoryCollection(new Dictionary <string, string>
            {
                { "AzureFunctionsJobHost:SequentialRestart", value },
            })
                                    .Build();

            _hostService = new WebJobsScriptHostService(
                _monitor, hostBuilder.Object, NullLoggerFactory.Instance,
                _mockScriptWebHostEnvironment.Object, _mockEnvironment.Object,
                _hostPerformanceManager, _healthMonitorOptions, metricsLogger,
                new Mock <IApplicationLifetime>().Object, config, new TestScriptEventManager());

            Assert.Equal(expectedResult, _hostService.ShouldEnforceSequentialRestart());
        }
        protected async Task <IWebHostBuilder> CreateWebHostBuilderAsync(string testDirName, IEnvironment environment)
        {
            var httpConfig         = new HttpConfiguration();
            var uniqueTestRootPath = Path.Combine(_testRootPath, testDirName, Guid.NewGuid().ToString());
            var scriptRootPath     = Path.Combine(uniqueTestRootPath, "wwwroot");

            FileUtility.EnsureDirectoryExists(scriptRootPath);
            string proxyConfigPath = Path.Combine(scriptRootPath, "proxies.json");

            File.WriteAllText(proxyConfigPath, "{}");
            await TestHelpers.Await(() => File.Exists(proxyConfigPath));

            _loggerProvider = new TestLoggerProvider();
            _metricsLogger  = new TestMetricsLogger();

            if (environment.IsAppService())
            {
                // if the test is mocking App Service environment, we need
                // to also set the HOME and WEBSITE_SITE_NAME variables
                environment.SetEnvironmentVariable(EnvironmentSettingNames.AzureWebsiteHomePath, uniqueTestRootPath);
                environment.SetEnvironmentVariable(EnvironmentSettingNames.AzureWebsiteName, "test-host-name");
            }

            var webHostBuilder = Program.CreateWebHostBuilder()
                                 .ConfigureAppConfiguration(c =>
            {
                // This source reads from AzureWebJobsScriptRoot, which does not work
                // with the custom paths that these tests are using.
                var source = c.Sources.OfType <WebScriptHostConfigurationSource>().SingleOrDefault();
                if (source != null)
                {
                    c.Sources.Remove(source);
                }
                c.AddTestSettings();
            })
                                 .ConfigureLogging(c =>
            {
                c.AddProvider(_loggerProvider);
                c.AddFilter((cat, lev) => true);
            })
                                 .ConfigureServices(c =>
            {
                c.ConfigureAll <ScriptApplicationHostOptions>(o =>
                {
                    o.IsSelfHost  = true;
                    o.LogPath     = Path.Combine(uniqueTestRootPath, "logs");
                    o.SecretsPath = Path.Combine(uniqueTestRootPath, "secrets");
                    o.ScriptPath  = _expectedScriptPath = scriptRootPath;
                });

                c.AddSingleton <IEnvironment>(_ => environment);
                c.AddSingleton <IMetricsLogger>(_ => _metricsLogger);
            })
                                 .ConfigureScriptHostLogging(b =>
            {
                b.AddProvider(_loggerProvider);
            });

            return(webHostBuilder);
        }
Ejemplo n.º 4
0
        public void LogInvocationMetrics_EmitsExpectedEvents()
        {
            var metrics = new TestMetricsLogger();
            Collection <BindingMetadata> bindings = new Collection <BindingMetadata>
            {
                new BindingMetadata {
                    Type = "httpTrigger"
                },
                new BindingMetadata {
                    Type = "blob", Direction = BindingDirection.In
                },
                new BindingMetadata {
                    Type = "blob", Direction = BindingDirection.Out
                },
                new BindingMetadata {
                    Type = "table", Direction = BindingDirection.In
                },
                new BindingMetadata {
                    Type = "table", Direction = BindingDirection.In
                }
            };

            FunctionInvokerBase.LogInvocationMetrics(metrics, bindings);

            Assert.Equal(6, metrics.LoggedEvents.Count);
            Assert.Equal("function.invoke", metrics.LoggedEvents[0]);
            Assert.Equal("function.binding.httpTrigger", metrics.LoggedEvents[1]);
            Assert.Equal("function.binding.blob.In", metrics.LoggedEvents[2]);
            Assert.Equal("function.binding.blob.Out", metrics.LoggedEvents[3]);
            Assert.Equal("function.binding.table.In", metrics.LoggedEvents[4]);
            Assert.Equal("function.binding.table.In", metrics.LoggedEvents[5]);
        }
        public async Task GetExtensionsStartupTypes_NonLegacyBundles_UsesBundlesForNonPrecompiledFunctions(bool hasPrecompiledFunctions)
        {
            using (var directory = GetTempDirectory())
            {
                TestMetricsLogger testMetricsLogger = new TestMetricsLogger();
                var testLogger = GetTestLogger();

                string bundlePath = hasPrecompiledFunctions ? "FakePath" : directory.Path;
                var    binPath    = Path.Combine(directory.Path, "bin");

                var mockExtensionBundleManager = new Mock <IExtensionBundleManager>();
                mockExtensionBundleManager.Setup(e => e.IsExtensionBundleConfigured()).Returns(true);
                mockExtensionBundleManager.Setup(e => e.GetExtensionBundleBinPathAsync()).Returns(Task.FromResult(binPath));
                mockExtensionBundleManager.Setup(e => e.IsLegacyExtensionBundle()).Returns(false);

                var mockFunctionMetadataManager = GetTestFunctionMetadataManager(hasPrecompiledFunction: hasPrecompiledFunctions);
                var discoverer = new ScriptStartupTypeLocator(directory.Path, testLogger, mockExtensionBundleManager.Object, mockFunctionMetadataManager, testMetricsLogger);

                // Act
                var types = await discoverer.GetExtensionsStartupTypesAsync();

                //Assert
                AreExpectedMetricsGenerated(testMetricsLogger);
                Assert.Single(types);
                Assert.Equal(typeof(AzureStorageWebJobsStartup).FullName, types.Single().FullName);
            }
        }
Ejemplo n.º 6
0
        public FunctionInvokerBaseTests()
        {
            _metricsLogger = new TestMetricsLogger();
            _traceWriter   = new TestTraceWriter(TraceLevel.Verbose);
            var config = new ScriptHostConfiguration();

            config.HostConfig.AddService <IMetricsLogger>(_metricsLogger);
            var funcDescriptor  = new FunctionDescriptor();
            var funcDescriptors = new Collection <FunctionDescriptor>();

            funcDescriptors.Add(funcDescriptor);
            var eventManager = new Mock <IScriptEventManager>();
            var hostMock     = new Mock <ScriptHost>(MockBehavior.Strict, new object[] { new NullScriptHostEnvironment(), eventManager.Object, config, null, null });

            hostMock.SetupGet(h => h.FunctionTraceWriterFactory).Returns(new FunctionTraceWriterFactory(config));
            hostMock.SetupGet(h => h.Functions).Returns(funcDescriptors);
            hostMock.Object.TraceWriter = _traceWriter;

            var metadata = new FunctionMetadata
            {
                Name = "TestFunction"
            };

            _invoker = new MockInvoker(hostMock.Object, _metricsLogger, metadata);
            funcDescriptor.Metadata = metadata;
            funcDescriptor.Invoker  = _invoker;
            funcDescriptor.Name     = metadata.Name;
        }
        public async Task GetExtensionsStartupTypes_ExtensionBundleReturnsNullPath_ReturnsNull()
        {
            var mockExtensionBundleManager = new Mock <IExtensionBundleManager>();

            mockExtensionBundleManager.Setup(e => e.IsExtensionBundleConfigured()).Returns(true);
            mockExtensionBundleManager.Setup(e => e.GetExtensionBundlePath()).ReturnsAsync(string.Empty);

            using (var directory = new TempDirectory())
            {
                TestLoggerProvider testLoggerProvider = new TestLoggerProvider();
                LoggerFactory      factory            = new LoggerFactory();
                TestMetricsLogger  testMetricsLogger  = new TestMetricsLogger();
                factory.AddProvider(testLoggerProvider);
                var testLogger = factory.CreateLogger <ScriptStartupTypeLocator>();

                var mockFunctionMetadataManager = GetTestFunctionMetadataManager(ImmutableArray <FunctionMetadata> .Empty);
                var discoverer = new ScriptStartupTypeLocator(string.Empty, testLogger, mockExtensionBundleManager.Object, mockFunctionMetadataManager, testMetricsLogger);

                // Act
                var types = await discoverer.GetExtensionsStartupTypesAsync();

                var traces = testLoggerProvider.GetAllLogMessages();

                // Assert
                AreExpectedMetricsGenerated(testMetricsLogger);
                Assert.NotNull(types);
                Assert.Equal(types.Count(), 0);
                Assert.True(traces.Any(m => string.Equals(m.FormattedMessage, $"Unable to find or download extension bundle")));
            }
        }
        public async Task GetExtensionsStartupTypes_RejectsBundleBelowMinimumVersion()
        {
            using (var directory = GetTempDirectory())
            {
                TestMetricsLogger  testMetricsLogger  = new TestMetricsLogger();
                TestLoggerProvider testLoggerProvider = new TestLoggerProvider();
                LoggerFactory      factory            = new LoggerFactory();
                factory.AddProvider(testLoggerProvider);
                var testLogger = factory.CreateLogger <ScriptStartupTypeLocator>();

                var binPath = Path.Combine(directory.Path, "bin");

                var mockExtensionBundleManager = new Mock <IExtensionBundleManager>();
                mockExtensionBundleManager.Setup(e => e.IsExtensionBundleConfigured()).Returns(true);
                mockExtensionBundleManager.Setup(e => e.GetExtensionBundleBinPathAsync()).Returns(Task.FromResult(binPath));
                mockExtensionBundleManager.Setup(e => e.IsLegacyExtensionBundle()).Returns(false);
                mockExtensionBundleManager.Setup(e => e.GetExtensionBundleDetails()).Returns(Task.FromResult(GetV2BundleDetails("2.1.0")));

                var mockFunctionMetadataManager = GetTestFunctionMetadataManager();
                var languageWorkerOptions       = new OptionsWrapper <LanguageWorkerOptions>(new LanguageWorkerOptions());
                var discoverer = new ScriptStartupTypeLocator(directory.Path, testLogger, mockExtensionBundleManager.Object, mockFunctionMetadataManager, testMetricsLogger, languageWorkerOptions);

                // Act
                var exception = await Assert.ThrowsAsync <HostInitializationException>(async() => await discoverer.GetExtensionsStartupTypesAsync());

                var traces = testLoggerProvider.GetAllLogMessages();

                // Assert
                Assert.True(traces.Any(m => string.Equals(m.FormattedMessage, $"Referenced bundle Microsoft.Azure.Functions.ExtensionBundle of version 2.1.0 does not meet the required minimum version of 2.6.1. Update your extension bundle reference in host.json to reference 2.6.1 or later.")));
            }
        }
        public void LogInvocationMetrics_EmitsExpectedEvents()
        {
            var metrics  = new TestMetricsLogger();
            var metadata = new FunctionMetadata
            {
                Name = "TestFunction"
            };

            metadata.Bindings.Add(new BindingMetadata {
                Type = "httpTrigger"
            });
            metadata.Bindings.Add(new BindingMetadata {
                Type = "blob", Direction = BindingDirection.In
            });
            metadata.Bindings.Add(new BindingMetadata {
                Type = "blob", Direction = BindingDirection.Out
            });
            metadata.Bindings.Add(new BindingMetadata {
                Type = "table", Direction = BindingDirection.In
            });
            metadata.Bindings.Add(new BindingMetadata {
                Type = "table", Direction = BindingDirection.In
            });
            var invokeLatencyEvent = FunctionInvokerBase.LogInvocationMetrics(metrics, metadata);

            Assert.Equal($"{MetricEventNames.FunctionInvokeLatency}_testfunction", (string)invokeLatencyEvent);

            Assert.Equal(5, metrics.LoggedEvents.Count);
            Assert.Equal("function.binding.httptrigger", metrics.LoggedEvents[0]);
            Assert.Equal("function.binding.blob.in", metrics.LoggedEvents[1]);
            Assert.Equal("function.binding.blob.out", metrics.LoggedEvents[2]);
            Assert.Equal("function.binding.table.in", metrics.LoggedEvents[3]);
            Assert.Equal("function.binding.table.in", metrics.LoggedEvents[4]);
        }
        public async Task GetExtensionsStartupTypes_LegacyBundles_UsesExtensionBundleBinaries(bool hasPrecompiledFunctions)
        {
            using (var directory = GetTempDirectory())
            {
                var binPath = Path.Combine(directory.Path, "bin");
                TestMetricsLogger testMetricsLogger = new TestMetricsLogger();
                var testLogger = GetTestLogger();

                var mockExtensionBundleManager = new Mock <IExtensionBundleManager>();
                mockExtensionBundleManager.Setup(e => e.IsExtensionBundleConfigured()).Returns(true);
                mockExtensionBundleManager.Setup(e => e.GetExtensionBundleBinPathAsync()).Returns(Task.FromResult(binPath));
                mockExtensionBundleManager.Setup(e => e.IsLegacyExtensionBundle()).Returns(true);
                mockExtensionBundleManager.Setup(e => e.GetExtensionBundleDetails()).Returns(Task.FromResult(GetV2BundleDetails()));

                var mockFunctionMetadataManager = GetTestFunctionMetadataManager(hasPrecompiledFunction: hasPrecompiledFunctions);
                var languageWorkerOptions       = new OptionsWrapper <LanguageWorkerOptions>(new LanguageWorkerOptions());
                var discoverer = new ScriptStartupTypeLocator(directory.Path, testLogger, mockExtensionBundleManager.Object, mockFunctionMetadataManager, testMetricsLogger, languageWorkerOptions);

                // Act
                var types = await discoverer.GetExtensionsStartupTypesAsync();

                //Assert
                AreExpectedMetricsGenerated(testMetricsLogger);
                Assert.Single(types);
                Assert.Equal(typeof(AzureStorageWebJobsStartup).FullName, types.Single().FullName);
            }
        }
Ejemplo n.º 11
0
        public async Task HostInitialization_OnInitializationException_MaintainsErrorInformation()
        {
            // When an exception is thrown, we'll create a new host. Make sure
            // we don't return the same one (with disposed services) the second time.
            var metricsLogger = new TestMetricsLogger();
            var hostA         = CreateMockHost();

            hostA.Setup(h => h.StartAsync(It.IsAny <CancellationToken>()))
            .Throws(new HostInitializationException("boom"));

            var hostB = CreateMockHost();

            hostB.Setup(h => h.StartAsync(It.IsAny <CancellationToken>()))
            .Returns(Task.CompletedTask);

            var hostBuilder = new Mock <IScriptHostBuilder>();

            hostBuilder.SetupSequence(b => b.BuildHost(It.IsAny <bool>(), It.IsAny <bool>()))
            .Returns(hostA.Object)
            .Returns(hostB.Object);

            _hostService = new WebJobsScriptHostService(
                _monitor, hostBuilder.Object, NullLoggerFactory.Instance,
                _mockScriptWebHostEnvironment.Object, _mockEnvironment.Object, _hostPerformanceManager, _healthMonitorOptions, metricsLogger, new Mock <IApplicationLifetime>().Object);

            await _hostService.StartAsync(CancellationToken.None);

            Assert.True(AreRequiredMetricsGenerated(metricsLogger));
            Assert.Equal(ScriptHostState.Error, _hostService.State);
            Assert.IsType <HostInitializationException>(_hostService.LastError);
        }
        public async Task StartAsync_Succeeds()
        {
            var hostBuilder = new Mock <IScriptHostBuilder>();

            hostBuilder.Setup(b => b.BuildHost(It.IsAny <bool>(), It.IsAny <bool>())).Returns(_host.Object);

            _webHostLoggerProvider = new TestLoggerProvider();
            _loggerFactory         = new LoggerFactory();
            _loggerFactory.AddProvider(_webHostLoggerProvider);

            var mockEventManager = new Mock <IScriptEventManager>(MockBehavior.Strict);

            mockEventManager.Setup(p => p.Publish(It.IsAny <HostStartEvent>()));

            var metricsLogger = new TestMetricsLogger();

            _hostService = new WebJobsScriptHostService(
                _monitor, hostBuilder.Object, _loggerFactory,
                _mockScriptWebHostEnvironment.Object, _mockEnvironment.Object,
                _hostPerformanceManager, _healthMonitorOptions,
                metricsLogger, new Mock <IApplicationLifetime>().Object,
                _mockConfig, mockEventManager.Object);

            await _hostService.StartAsync(CancellationToken.None);

            // add general post startup validations here
            mockEventManager.Verify(_ => _.Publish(It.IsAny <HostStartEvent>()), Times.Once());
        }
        public async Task GetExtensionsStartupTypes_BundlesConfiguredBindingsConfigured_PerformsSelectiveLoading()
        {
            var storageExtensionReference = new ExtensionReference {
                Name = "Storage", TypeName = typeof(AzureStorageWebJobsStartup).AssemblyQualifiedName
            };

            storageExtensionReference.Bindings.Add("blob");
            var sendGridExtensionReference = new ExtensionReference {
                Name = "SendGrid", TypeName = typeof(AzureStorageWebJobsStartup).AssemblyQualifiedName
            };

            sendGridExtensionReference.Bindings.Add("sendGrid");
            var references = new[] { storageExtensionReference, sendGridExtensionReference };
            TestMetricsLogger testMetricsLogger = new TestMetricsLogger();

            var extensions = new JObject
            {
                { "extensions", JArray.FromObject(references) }
            };

            using (var directory = new TempDirectory())
            {
                var binPath = Path.Combine(directory.Path, "bin");
                Directory.CreateDirectory(binPath);

                void CopyToBin(string path)
                {
                    File.Copy(path, Path.Combine(binPath, Path.GetFileName(path)));
                }

                CopyToBin(typeof(AzureStorageWebJobsStartup).Assembly.Location);

                File.WriteAllText(Path.Combine(binPath, "extensions.json"), extensions.ToString());

                TestLoggerProvider testLoggerProvider = new TestLoggerProvider();
                LoggerFactory      factory            = new LoggerFactory();
                factory.AddProvider(testLoggerProvider);
                var testLogger = factory.CreateLogger <ScriptStartupTypeLocator>();

                var mockFunctionMetadataManager = GetTestFunctionMetadataManager();

                var mockExtensionBundleManager = new Mock <IExtensionBundleManager>();
                mockExtensionBundleManager.Setup(e => e.IsExtensionBundleConfigured()).Returns(true);
                mockExtensionBundleManager.Setup(e => e.GetExtensionBundleBinPathAsync()).Returns(Task.FromResult(binPath));
                mockExtensionBundleManager.Setup(e => e.GetExtensionBundleDetails()).Returns(Task.FromResult(GetV2BundleDetails()));
                var languageWorkerOptions = new OptionsWrapper <LanguageWorkerOptions>(new LanguageWorkerOptions());
                var discoverer            = new ScriptStartupTypeLocator(directory.Path, testLogger, mockExtensionBundleManager.Object, mockFunctionMetadataManager, testMetricsLogger, languageWorkerOptions);

                // Act
                var types = await discoverer.GetExtensionsStartupTypesAsync();

                //Assert
                AreExpectedMetricsGenerated(testMetricsLogger);
                Assert.Single(types);
                Assert.Equal(typeof(AzureStorageWebJobsStartup).FullName, types.Single().FullName);
            }
        }
Ejemplo n.º 14
0
 public FunctionMetadataProviderTests()
 {
     _testMetricsLogger            = new TestMetricsLogger();
     _scriptApplicationHostOptions = new ScriptApplicationHostOptions();
     _languageWorkerOptions        = new LanguageWorkerOptions
     {
         WorkerConfigs = TestHelpers.GetTestWorkerConfigs()
     };
 }
        public async Task DisposesScriptHost()
        {
            var metricsLogger = new TestMetricsLogger();

            var services = new ServiceCollection()
                           .AddLogging(l =>
            {
                l.Services.AddSingleton <ILoggerProvider, TestLoggerProvider>();
                l.AddFilter(_ => true);
            })
                           .BuildServiceProvider();

            var host = new Mock <IHost>();

            host.Setup(h => h.Services)
            .Returns(services);

            host.Setup(h => h.Dispose())
            .Callback(() =>
            {
                services.Dispose();
            });

            var hostBuilder = new Mock <IScriptHostBuilder>();

            hostBuilder.Setup(b => b.BuildHost(It.IsAny <bool>(), It.IsAny <bool>()))
            .Returns(host.Object);

            _webHostLoggerProvider = new TestLoggerProvider();
            _loggerFactory         = new LoggerFactory();
            _loggerFactory.AddProvider(_webHostLoggerProvider);

            _hostService = new WebJobsScriptHostService(
                _monitor, hostBuilder.Object, _loggerFactory,
                _mockScriptWebHostEnvironment.Object, _mockEnvironment.Object,
                _hostPerformanceManager, _healthMonitorOptions,
                metricsLogger, new Mock <IApplicationLifetime>().Object,
                _mockConfig, new TestScriptEventManager());

            var hostLogger = host.Object.GetTestLoggerProvider();

            await _hostService.StartAsync(CancellationToken.None);

            await _hostService.RestartHostAsync(CancellationToken.None);

            Assert.True(AreRequiredMetricsGenerated(metricsLogger));

            host.Verify(m => m.StopAsync(It.IsAny <CancellationToken>()), Times.Exactly(1));
            host.Verify(m => m.Dispose(), Times.Exactly(1));

            var allLogMessages = _webHostLoggerProvider.GetAllLogMessages();

            Assert.Contains(allLogMessages,
                            m => m.FormattedMessage != null &&
                            m.FormattedMessage.Contains("ScriptHost disposed"));
        }
        public async Task Specialize_StandbyManagerInitialize_EmitsExpectedMetric()
        {
            TestMetricsLogger metricsLogger = new TestMetricsLogger();

            _testEnvironment.SetEnvironmentVariable(EnvironmentSettingNames.AzureWebsiteHostName, "placeholder.azurewebsites.net");

            var hostNameProvider = new HostNameProvider(_testEnvironment);
            var manager          = new StandbyManager(_mockHostManager.Object, _mockLanguageWorkerChannelManager.Object, _mockConfiguration.Object, _mockWebHostEnvironment.Object, _testEnvironment, _mockOptionsMonitor.Object, NullLogger <StandbyManager> .Instance, hostNameProvider, _mockApplicationLifetime.Object, metricsLogger);
            await manager.InitializeAsync().ContinueWith(t => { }); // Ignore errors.

            // Ensure metric is generated
            Assert.True(metricsLogger.EventsBegan.Contains(MetricEventNames.SpecializationStandbyManagerInitialize) && metricsLogger.EventsEnded.Contains(MetricEventNames.SpecializationStandbyManagerInitialize));
        }
        public async Task Specialize_ResetsConfiguration()
        {
            TestMetricsLogger metricsLogger = new TestMetricsLogger();
            var hostNameProvider            = new HostNameProvider(_testEnvironment);
            var manager = new StandbyManager(_mockHostManager.Object, _mockLanguageWorkerChannelManager.Object, _mockConfiguration.Object, _mockWebHostEnvironment.Object, _testEnvironment, _mockOptionsMonitor.Object, NullLogger <StandbyManager> .Instance, hostNameProvider, _mockApplicationLifetime.Object, metricsLogger);

            await manager.SpecializeHostAsync();

            // Ensure metrics are generated
            Assert.True(AreExpectedMetricsGenerated(metricsLogger));

            _mockConfiguration.Verify(c => c.Reload());
        }
        public async Task GetExtensionsStartupTypes_BundlesNotConfiguredBindingsNotConfigured_LoadsAllExtensions()
        {
            var references = new[]
            {
                new ExtensionReference {
                    Name = "Storage", TypeName = typeof(AzureStorageWebJobsStartup).AssemblyQualifiedName
                }
            };

            var extensions = new JObject
            {
                { "extensions", JArray.FromObject(references) }
            };

            var mockExtensionBundleManager      = new Mock <IExtensionBundleManager>();
            TestMetricsLogger testMetricsLogger = new TestMetricsLogger();

            mockExtensionBundleManager.Setup(e => e.IsExtensionBundleConfigured()).Returns(false);

            using (var directory = new TempDirectory())
            {
                var binPath = Path.Combine(directory.Path, "bin");
                Directory.CreateDirectory(binPath);

                void CopyToBin(string path)
                {
                    File.Copy(path, Path.Combine(binPath, Path.GetFileName(path)));
                }

                CopyToBin(typeof(AzureStorageWebJobsStartup).Assembly.Location);

                File.WriteAllText(Path.Combine(binPath, "extensions.json"), extensions.ToString());

                TestLoggerProvider testLoggerProvider = new TestLoggerProvider();
                LoggerFactory      factory            = new LoggerFactory();
                factory.AddProvider(testLoggerProvider);
                var testLogger = factory.CreateLogger <ScriptStartupTypeLocator>();

                // mock Function metadata
                var mockFunctionMetadataManager = GetTestFunctionMetadataManager(ImmutableArray <FunctionMetadata> .Empty);
                var discoverer = new ScriptStartupTypeLocator(directory.Path, testLogger, mockExtensionBundleManager.Object, mockFunctionMetadataManager, testMetricsLogger);

                // Act
                var types = await discoverer.GetExtensionsStartupTypesAsync();

                // Assert
                AreExpectedMetricsGenerated(testMetricsLogger);
                Assert.Single(types);
                Assert.Equal(typeof(AzureStorageWebJobsStartup).FullName, types.Single().FullName);
            }
        }
        public async Task DisposedHost_ServicesNotExposed()
        {
            SemaphoreSlim blockingSemaphore = new SemaphoreSlim(0, 1);
            SemaphoreSlim disposedSemaphore = new SemaphoreSlim(0, 1);
            var           metricsLogger     = new TestMetricsLogger();

            // Have the first host throw upon starting. Then pause while building the second
            // host. When accessing Services then, they should be null, rather than disposed.
            var hostA = CreateMockHost(disposedSemaphore);

            hostA
            .Setup(h => h.StartAsync(It.IsAny <CancellationToken>()))
            .Returns(() =>
            {
                throw new InvalidOperationException("Something happened at startup!");
            });

            var hostB = CreateMockHost();

            hostB
            .Setup(h => h.StartAsync(It.IsAny <CancellationToken>()))
            .Returns(async() =>
            {
                await blockingSemaphore.WaitAsync();
            });

            var hostBuilder = new Mock <IScriptHostBuilder>();

            hostBuilder.SetupSequence(b => b.BuildHost(It.IsAny <bool>(), It.IsAny <bool>()))
            .Returns(hostA.Object)
            .Returns(hostB.Object);

            _hostService = new WebJobsScriptHostService(
                _monitor, hostBuilder.Object, NullLoggerFactory.Instance,
                _mockScriptWebHostEnvironment.Object, _mockEnvironment.Object,
                _hostPerformanceManager, _healthMonitorOptions, metricsLogger,
                new Mock <IApplicationLifetime>().Object, _mockConfig, new TestScriptEventManager());

            Task startTask = _hostService.StartAsync(CancellationToken.None);

            await disposedSemaphore.WaitAsync();

            Assert.Null(_hostService.Services);

            blockingSemaphore.Release();

            await startTask;

            Assert.True(AreRequiredMetricsGenerated(metricsLogger));
        }
        public async Task HostRestart_BeforeStart_WaitsForStartToContinue()
        {
            _host = CreateMockHost();
            var metricsLogger = new TestMetricsLogger();
            var hostBuilder   = new Mock <IScriptHostBuilder>();

            hostBuilder.SetupSequence(b => b.BuildHost(It.IsAny <bool>(), It.IsAny <bool>()))
            .Returns(_host.Object)
            .Returns(_host.Object);

            _webHostLoggerProvider = new TestLoggerProvider();
            _loggerFactory         = new LoggerFactory();
            _loggerFactory.AddProvider(_webHostLoggerProvider);

            _hostService = new WebJobsScriptHostService(
                _monitor, hostBuilder.Object, _loggerFactory,
                _mockScriptWebHostEnvironment.Object, _mockEnvironment.Object,
                _hostPerformanceManager, _healthMonitorOptions, metricsLogger,
                new Mock <IApplicationLifetime>().Object, _mockConfig, new TestScriptEventManager());

            // Simulate a call to specialize coming from the PlaceholderSpecializationMiddleware. This
            // can happen before we ever start the service, which could create invalid state.
            Task restartTask = _hostService.RestartHostAsync(CancellationToken.None);

            await _hostService.StartAsync(CancellationToken.None);

            await restartTask;

            // Ensure metrics are added
            Assert.True(AreRequiredMetricsGenerated(metricsLogger));
            Assert.True(metricsLogger.EventsBegan.Contains(MetricEventNames.ScriptHostManagerRestartService));
            Assert.True(metricsLogger.EventsEnded.Contains(MetricEventNames.ScriptHostManagerRestartService));
            Assert.True(metricsLogger.EventsBegan.Contains(MetricEventNames.ScriptHostManagerBuildScriptHost));
            Assert.True(metricsLogger.EventsBegan.Contains(MetricEventNames.ScriptHostManagerBuildScriptHost));
            Assert.True(metricsLogger.EventsBegan.Contains(MetricEventNames.ScriptHostManagerStartScriptHost));
            Assert.True(metricsLogger.EventsBegan.Contains(MetricEventNames.ScriptHostManagerStartScriptHost));

            var messages = _webHostLoggerProvider.GetAllLogMessages();

            // The CancellationToken is canceled quick enough that we never build the initial host, so the
            // only one we start is the restarted/specialized one.
            Assert.NotNull(messages.Single(p => p.EventId.Id == 513)); // "Building" message
            Assert.NotNull(messages.Single(p => p.EventId.Id == 514)); // "StartupWasCanceled" message
            Assert.NotNull(messages.Single(p => p.EventId.Id == 520)); // "RestartBeforeStart" message
            _host.Verify(p => p.StartAsync(It.IsAny <CancellationToken>()), Times.Once);
        }
        public async Task GetExtensionsStartupTypes_RejectsExtensionsBelowMinimumVersion()
        {
            var mockExtensionBundleManager      = new Mock <IExtensionBundleManager>();
            TestMetricsLogger testMetricsLogger = new TestMetricsLogger();

            mockExtensionBundleManager.Setup(e => e.IsExtensionBundleConfigured()).Returns(false);

            using (var directory = new TempDirectory())
            {
                var binPath = Path.Combine(directory.Path, "bin");
                Directory.CreateDirectory(binPath);

                void CopyToBin(string path)
                {
                    File.Copy(path, Path.Combine(binPath, Path.GetFileName(path)));
                }

                // create a bin folder that has out of date extensions
                var extensionBinPath = Path.Combine(Environment.CurrentDirectory, @"TestScripts\OutOfDateExtension\bin");
                foreach (var f in Directory.GetFiles(extensionBinPath))
                {
                    CopyToBin(f);
                }
                TestLoggerProvider testLoggerProvider = new TestLoggerProvider();
                LoggerFactory      factory            = new LoggerFactory();
                factory.AddProvider(testLoggerProvider);
                var testLogger = factory.CreateLogger <ScriptStartupTypeLocator>();

                var mockFunctionMetadataManager = GetTestFunctionMetadataManager(ImmutableArray <FunctionMetadata> .Empty);
                var languageWorkerOptions       = new OptionsWrapper <LanguageWorkerOptions>(new LanguageWorkerOptions());
                var discoverer = new ScriptStartupTypeLocator(directory.Path, testLogger, mockExtensionBundleManager.Object, mockFunctionMetadataManager, testMetricsLogger, languageWorkerOptions);

                // Act
                var exception = await Assert.ThrowsAsync <HostInitializationException>(async() => await discoverer.GetExtensionsStartupTypesAsync());

                var traces = testLoggerProvider.GetAllLogMessages();

                // Assert

                var storageTrace = traces.FirstOrDefault(m => m.FormattedMessage.StartsWith("ExtensionStartupType AzureStorageWebJobsStartup"));
                Assert.NotNull(storageTrace);
                Assert.Equal("ExtensionStartupType AzureStorageWebJobsStartup from assembly 'Microsoft.Azure.WebJobs.Extensions.Storage, Version=3.0.10.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' does not meet the required minimum version of 4.0.4.0. Update your NuGet package reference for Microsoft.Azure.WebJobs.Extensions.Storage to 4.0.4 or later.",
                             storageTrace.FormattedMessage);
            }
        }
        public FunctionInvokerBaseTests()
        {
            _metricsLogger = new TestMetricsLogger();
            _traceWriter   = new TestTraceWriter(TraceLevel.Verbose);
            var config = new ScriptHostConfiguration();

            config.HostConfig.AddService <IMetricsLogger>(_metricsLogger);
            var hostMock = new Mock <ScriptHost>(MockBehavior.Strict, new object[] { new NullScriptHostEnvironment(), config, null });

            hostMock.Object.TraceWriter = _traceWriter;

            var metadata = new FunctionMetadata
            {
                Name = "TestFunction"
            };

            _invoker = new MockInvoker(hostMock.Object, metadata);
        }
Ejemplo n.º 23
0
        public FunctionInvokerBaseTests()
        {
            _metricsLogger      = new TestMetricsLogger();
            _testLoggerProvider = new TestLoggerProvider();

            var scriptHostConfiguration = new ScriptHostConfiguration
            {
                HostConfig          = new JobHostConfiguration(),
                FileLoggingMode     = FileLoggingMode.Always,
                FileWatchingEnabled = true
            };

            ILoggerFactory loggerFactory = new LoggerFactory();

            loggerFactory.AddProvider(_testLoggerProvider);
            scriptHostConfiguration.HostConfig.LoggerFactory = loggerFactory;

            scriptHostConfiguration.HostConfig.AddService <IMetricsLogger>(_metricsLogger);

            var eventManager = new ScriptEventManager();

            var host = new Mock <ScriptHost>(new NullScriptHostEnvironment(), eventManager, scriptHostConfiguration, null, null, null);

            host.CallBase = true;

            host.SetupGet(h => h.IsPrimary).Returns(true);

            var funcDescriptor  = new FunctionDescriptor();
            var funcDescriptors = new Collection <FunctionDescriptor>();

            funcDescriptors.Add(funcDescriptor);
            host.SetupGet(h => h.Functions).Returns(funcDescriptors);

            var metadata = new FunctionMetadata
            {
                Name = "TestFunction"
            };

            _invoker = new MockInvoker(host.Object, _metricsLogger, metadata);
            funcDescriptor.Metadata = metadata;
            funcDescriptor.Invoker  = _invoker;
            funcDescriptor.Name     = metadata.Name;
        }
        public FunctionInvokerBaseTests()
        {
            _metricsLogger      = new TestMetricsLogger();
            _testLoggerProvider = new TestLoggerProvider();

            ILoggerFactory loggerFactory = new LoggerFactory();

            loggerFactory.AddProvider(_testLoggerProvider);

            var eventManager = new ScriptEventManager();

            var metadata = new FunctionMetadata
            {
                Name       = "TestFunction",
                ScriptFile = "index.js",
                Language   = "node"
            };
            JObject binding = JObject.FromObject(new
            {
                type      = "manualTrigger",
                name      = "manual",
                direction = "in"
            });

            metadata.Bindings.Add(BindingMetadata.Create(binding));

            var metadataManager = new MockMetadataManager(new[] { metadata });

            _host = new HostBuilder()
                    .ConfigureDefaultTestWebScriptHost()
                    .ConfigureServices(s =>
            {
                s.AddSingleton <IFunctionMetadataManager>(metadataManager);
            })
                    .Build();

            _scriptHost = _host.GetScriptHost();
            _scriptHost.InitializeAsync().Wait();

            _invoker = new MockInvoker(_scriptHost, _metricsLogger, metadataManager, metadata, loggerFactory);
        }
        public async Task Specialize_ReloadsEnvironmentVariables()
        {
            TestMetricsLogger metricsLogger = new TestMetricsLogger();

            _testEnvironment.SetEnvironmentVariable(RpcWorkerConstants.FunctionWorkerRuntimeSettingName, RpcWorkerConstants.JavaLanguageWorkerName);
            _mockLanguageWorkerChannelManager.Setup(m => m.SpecializeAsync()).Returns(async() =>
            {
                _testEnvironment.SetEnvironmentVariable(_testSettingName, _testSettingValue);
                await Task.Yield();
            });
            _testEnvironment.SetEnvironmentVariable(RpcWorkerConstants.FunctionWorkerRuntimeSettingName, RpcWorkerConstants.JavaLanguageWorkerName);

            var hostNameProvider = new HostNameProvider(_testEnvironment);
            var manager          = new StandbyManager(_mockHostManager.Object, _mockLanguageWorkerChannelManager.Object, _mockConfiguration.Object, _mockWebHostEnvironment.Object, _testEnvironment, _mockOptionsMonitor.Object, NullLogger <StandbyManager> .Instance, hostNameProvider, _mockApplicationLifetime.Object, metricsLogger);
            await manager.SpecializeHostAsync();

            // Ensure metrics are generated
            Assert.True(AreExpectedMetricsGenerated(metricsLogger));

            Assert.Equal(_testSettingValue, _testEnvironment.GetEnvironmentVariable(_testSettingName));
        }
        public async Task Specialize_ResetsHostNameProvider()
        {
            TestMetricsLogger metricsLogger = new TestMetricsLogger();

            _testEnvironment.SetEnvironmentVariable(EnvironmentSettingNames.AzureWebsiteHostName, "placeholder.azurewebsites.net");

            var hostNameProvider = new HostNameProvider(_testEnvironment);
            var manager          = new StandbyManager(_mockHostManager.Object, _mockLanguageWorkerChannelManager.Object, _mockConfiguration.Object, _mockWebHostEnvironment.Object, _testEnvironment, _mockOptionsMonitor.Object, NullLogger <StandbyManager> .Instance, hostNameProvider, _mockApplicationLifetime.Object, metricsLogger);

            Assert.Equal("placeholder.azurewebsites.net", hostNameProvider.Value);

            await manager.SpecializeHostAsync();

            // Ensure metrics are generated
            Assert.True(AreExpectedMetricsGenerated(metricsLogger));

            _testEnvironment.SetEnvironmentVariable(EnvironmentSettingNames.AzureWebsiteHostName, "testapp.azurewebsites.net");
            Assert.Equal("testapp.azurewebsites.net", hostNameProvider.Value);

            _mockConfiguration.Verify(c => c.Reload());
        }
        public async Task HostRestart_Specialization_Succeeds()
        {
            var metricsLogger = new TestMetricsLogger();

            _host.Setup(h => h.StartAsync(It.IsAny <CancellationToken>()))
            .Returns(Task.CompletedTask);

            var hostBuilder = new Mock <IScriptHostBuilder>();

            hostBuilder.Setup(b => b.BuildHost(It.IsAny <bool>(), It.IsAny <bool>()))
            .Returns(_host.Object);

            _webHostLoggerProvider = new TestLoggerProvider();
            _loggerFactory         = new LoggerFactory();
            _loggerFactory.AddProvider(_webHostLoggerProvider);

            _hostService = new WebJobsScriptHostService(
                _monitor, hostBuilder.Object, _loggerFactory,
                _mockScriptWebHostEnvironment.Object, _mockEnvironment.Object,
                _hostPerformanceManager, _healthMonitorOptions,
                metricsLogger, new Mock <IApplicationLifetime>().Object,
                _mockConfig, new TestScriptEventManager());

            await _hostService.StartAsync(CancellationToken.None);

            Assert.True(AreRequiredMetricsGenerated(metricsLogger));

            Thread restartHostThread    = new Thread(new ThreadStart(RestartHost));
            Thread specializeHostThread = new Thread(new ThreadStart(SpecializeHost));

            restartHostThread.Start();
            specializeHostThread.Start();
            restartHostThread.Join();
            specializeHostThread.Join();

            var logMessages = _webHostLoggerProvider.GetAllLogMessages().Where(m => m.FormattedMessage.Contains("Restarting host."));

            Assert.Equal(2, logMessages.Count());
        }
Ejemplo n.º 28
0
        private bool AreRequiredMetricsEmitted(TestMetricsLogger metricsLogger)
        {
            bool hasBegun = false;
            bool hasEnded = false;

            foreach (string begin in metricsLogger.EventsBegan)
            {
                if (begin.Contains(MetricEventNames.ReadFunctionMetadata.Substring(0, MetricEventNames.ReadFunctionMetadata.IndexOf('{'))))
                {
                    hasBegun = true;
                    break;
                }
            }
            foreach (string end in metricsLogger.EventsEnded)
            {
                if (end.Contains(MetricEventNames.ReadFunctionMetadata.Substring(0, MetricEventNames.ReadFunctionMetadata.IndexOf('{'))))
                {
                    hasEnded = true;
                    break;
                }
            }
            return(hasBegun && hasEnded && (metricsLogger.EventsBegan.Contains(MetricEventNames.ReadFunctionsMetadata) &&
                                            metricsLogger.EventsEnded.Contains(MetricEventNames.ReadFunctionsMetadata)));
        }
 private bool AreExpectedMetricsGenerated(TestMetricsLogger metricsLogger)
 {
     return(metricsLogger.EventsBegan.Contains(MetricEventNames.ParseExtensions) && metricsLogger.EventsEnded.Contains(MetricEventNames.ParseExtensions));
 }
        public async Task GetExtensionsStartupTypes_FiltersBuiltinExtensionsAsync()
        {
            var references = new[]
            {
                new ExtensionReference {
                    Name = "Http", TypeName = typeof(HttpWebJobsStartup).AssemblyQualifiedName
                },
                new ExtensionReference {
                    Name = "Timers", TypeName = typeof(ExtensionsWebJobsStartup).AssemblyQualifiedName
                },
                new ExtensionReference {
                    Name = "Storage", TypeName = typeof(AzureStorageWebJobsStartup).AssemblyQualifiedName
                },
            };

            var extensions = new JObject
            {
                { "extensions", JArray.FromObject(references) }
            };

            var mockExtensionBundleManager      = new Mock <IExtensionBundleManager>();
            TestMetricsLogger testMetricsLogger = new TestMetricsLogger();

            mockExtensionBundleManager.Setup(e => e.IsExtensionBundleConfigured()).Returns(false);

            using (var directory = new TempDirectory())
            {
                var binPath = Path.Combine(directory.Path, "bin");
                Directory.CreateDirectory(binPath);

                void CopyToBin(string path)
                {
                    File.Copy(path, Path.Combine(binPath, Path.GetFileName(path)));
                }

                CopyToBin(typeof(HttpWebJobsStartup).Assembly.Location);
                CopyToBin(typeof(ExtensionsWebJobsStartup).Assembly.Location);
                CopyToBin(typeof(AzureStorageWebJobsStartup).Assembly.Location);

                File.WriteAllText(Path.Combine(binPath, "extensions.json"), extensions.ToString());

                TestLoggerProvider testLoggerProvider = new TestLoggerProvider();
                LoggerFactory      factory            = new LoggerFactory();
                factory.AddProvider(testLoggerProvider);
                var testLogger = factory.CreateLogger <ScriptStartupTypeLocator>();

                var mockFunctionMetadataManager = GetTestFunctionMetadataManager(ImmutableArray <FunctionMetadata> .Empty);
                var discoverer = new ScriptStartupTypeLocator(directory.Path, testLogger, mockExtensionBundleManager.Object, mockFunctionMetadataManager, testMetricsLogger);

                // Act
                var types = await discoverer.GetExtensionsStartupTypesAsync();

                var traces = testLoggerProvider.GetAllLogMessages();

                // Assert
                AreExpectedMetricsGenerated(testMetricsLogger);
                Assert.Single(types);
                Assert.Equal(typeof(AzureStorageWebJobsStartup).FullName, types.Single().FullName);
                Assert.True(traces.Any(m => string.Equals(m.FormattedMessage, $"The extension startup type '{references[0].TypeName}' belongs to a builtin extension")));
                Assert.True(traces.Any(m => string.Equals(m.FormattedMessage, $"The extension startup type '{references[1].TypeName}' belongs to a builtin extension")));
            }
        }