Beispiel #1
0
        public TestFunctionHost(string scriptPath, string logPath,
                                Action <IWebJobsBuilder> configureJobHost = null,
                                Action <IConfigurationBuilder> configureAppConfiguration = null,
                                Action <IServiceCollection> configureServices            = null)
        {
            _appRoot = scriptPath;

            _hostOptions = new ScriptApplicationHostOptions
            {
                IsSelfHost     = true,
                ScriptPath     = _appRoot,
                LogPath        = logPath,
                SecretsPath    = Environment.CurrentDirectory, // not used
                HasParentScope = true
            };

            var optionsMonitor = TestHelpers.CreateOptionsMonitor(_hostOptions);
            var builder        = new WebHostBuilder()
                                 .ConfigureLogging(b =>
            {
                b.AddProvider(_loggerProvider);
            })
                                 .ConfigureServices(services =>
            {
                services.Replace(new ServiceDescriptor(typeof(ISecretManagerProvider), new TestSecretManagerProvider(new TestSecretManager())));
                services.Replace(ServiceDescriptor.Singleton <IServiceProviderFactory <IServiceCollection> >(new WebHostServiceProviderFactory()));
                services.Replace(new ServiceDescriptor(typeof(IOptions <ScriptApplicationHostOptions>), new OptionsWrapper <ScriptApplicationHostOptions>(_hostOptions)));
                services.Replace(new ServiceDescriptor(typeof(IOptionsMonitor <ScriptApplicationHostOptions>), optionsMonitor));

                services.AddSingleton <IConfigureBuilder <IConfigurationBuilder> >(_ => new DelegatedConfigureBuilder <IConfigurationBuilder>(c =>
                {
                    c.AddTestSettings();
                    configureAppConfiguration?.Invoke(c);
                }));

                configureServices?.Invoke(services);
            })
                                 .AddScriptHostBuilder(webJobsBuilder =>
            {
                var loggingBuilder = new LoggingBuilder(webJobsBuilder.Services);
                loggingBuilder.AddProvider(_loggerProvider);
                loggingBuilder.AddFilter <TestLoggerProvider>(_ => true);

                webJobsBuilder.AddAzureStorage();

                configureJobHost?.Invoke(webJobsBuilder);
            })
                                 .UseStartup <Startup>();

            _testServer = new TestServer(builder);

            HttpClient             = new HttpClient(new UpdateContentLengthHandler(_testServer.CreateHandler()));
            HttpClient.BaseAddress = new Uri("https://localhost/");

            var manager = _testServer.Host.Services.GetService <IScriptHostManager>();

            _hostService = manager as WebJobsScriptHostService;

            StartAsync().GetAwaiter().GetResult();
        }
        public void ReadFunctionMetadata_With_Retry_Succeeds()
        {
            string functionsPath = Path.Combine(Environment.CurrentDirectory, @"..\..\..\..\..\sample\noderetry");

            _scriptApplicationHostOptions.ScriptPath = functionsPath;
            var optionsMonitor    = TestHelpers.CreateOptionsMonitor(_scriptApplicationHostOptions);
            var metadataProvider  = new FunctionMetadataProvider(optionsMonitor, NullLogger <FunctionMetadataProvider> .Instance, _testMetricsLogger);
            var workerConfigs     = TestHelpers.GetTestWorkerConfigs();
            var functionMetadatas = metadataProvider.GetFunctionMetadata(workerConfigs, false);

            Assert.Equal(2, functionMetadatas.Length);

            var functionMetadataWithRetry = functionMetadatas.Where(f => f.Name.Contains("HttpTrigger-RetryFunctionJson", StringComparison.OrdinalIgnoreCase));

            Assert.Single(functionMetadataWithRetry);
            var retry = functionMetadataWithRetry.FirstOrDefault().Retry;

            Assert.NotNull(retry);
            Assert.Equal(RetryStrategy.FixedDelay, retry.Strategy);
            Assert.Equal(4, retry.MaxRetryCount);
            Assert.Equal(TimeSpan.Parse("00:00:03"), retry.DelayInterval);

            var functionMetadata = functionMetadatas.Where(f => !f.Name.Contains("HttpTrigger-RetryFunctionJson", StringComparison.OrdinalIgnoreCase));

            Assert.Single(functionMetadataWithRetry);
            Assert.Null(functionMetadata.FirstOrDefault().Retry);
        }
Beispiel #3
0
        public void ReadFunctionMetadata_For_WorkerIndexingFormatApp_Fails()
        {
            string functionsPath = Path.Combine(Environment.CurrentDirectory, @"..", "..", "..", "..", "..", "sample", "PythonWorkerIndexing");

            _scriptApplicationHostOptions.ScriptPath = functionsPath;
            var optionsMonitor   = TestHelpers.CreateOptionsMonitor(_scriptApplicationHostOptions);
            var metadataProvider = new HostFunctionMetadataProvider(optionsMonitor, NullLogger <HostFunctionMetadataProvider> .Instance, _testMetricsLogger);
            var workerConfigs    = TestHelpers.GetTestWorkerConfigs();

            Assert.Equal(0, metadataProvider.GetFunctionMetadataAsync(workerConfigs, SystemEnvironment.Instance, false).Result.Length);
        }
        public void ReadFunctionMetadata_Succeeds()
        {
            string functionsPath = Path.Combine(Environment.CurrentDirectory, @"..\..\..\..\..\sample\node");

            _scriptApplicationHostOptions.ScriptPath = functionsPath;
            var optionsMonitor   = TestHelpers.CreateOptionsMonitor(_scriptApplicationHostOptions);
            var metadataProvider = new FunctionMetadataProvider(optionsMonitor, new OptionsWrapper <LanguageWorkerOptions>(_languageWorkerOptions), NullLogger <FunctionMetadataProvider> .Instance, _testMetricsLogger);

            Assert.Equal(17, metadataProvider.GetFunctionMetadata(false).Length);
            Assert.True(AreRequiredMetricsEmitted(_testMetricsLogger));
        }
Beispiel #5
0
        public void ReadFunctionMetadata_Succeeds()
        {
            string functionsPath = Path.Combine(Environment.CurrentDirectory, @"..", "..", "..", "..", "..", "sample", "node");

            _scriptApplicationHostOptions.ScriptPath = functionsPath;
            var optionsMonitor   = TestHelpers.CreateOptionsMonitor(_scriptApplicationHostOptions);
            var metadataProvider = new HostFunctionMetadataProvider(optionsMonitor, NullLogger <HostFunctionMetadataProvider> .Instance, _testMetricsLogger);
            var workerConfigs    = TestHelpers.GetTestWorkerConfigs();

            Assert.Equal(18, metadataProvider.GetFunctionMetadataAsync(workerConfigs, SystemEnvironment.Instance, false).Result.Length);
            Assert.True(AreRequiredMetricsEmitted(_testMetricsLogger));
        }
            public TestFixture()
            {
                // copy test files to temp directory, since accessing the metadata APIs will result
                // in file creations (for test data files)
                var scriptSource = Path.Combine(Environment.CurrentDirectory, "..", "..", "..", "TestScripts", "WarmupFunction");

                _testHome = Path.Combine(Path.GetTempPath(), @"WarmupFunction");
                var scriptRoot = Path.Combine(_testHome, "site", "wwwroot");

                FileUtility.CopyDirectory(scriptSource, scriptRoot);

                HostOptions = new ScriptApplicationHostOptions
                {
                    IsSelfHost   = true,
                    ScriptPath   = scriptRoot,
                    LogPath      = Path.Combine(_testHome, "LogFiles", "Application", "Functions"),
                    SecretsPath  = Path.Combine(_testHome, "data", "Functions", "Secrets"),
                    TestDataPath = Path.Combine(_testHome, "data", "Functions", "SampleData")
                };

                FileUtility.EnsureDirectoryExists(HostOptions.TestDataPath);

                var optionsMonitor = TestHelpers.CreateOptionsMonitor(HostOptions);

                var workerOptions = new LanguageWorkerOptions
                {
                    WorkerConfigs = TestHelpers.GetTestWorkerConfigs()
                };

                var provider = new HostFunctionMetadataProvider(optionsMonitor, NullLogger <HostFunctionMetadataProvider> .Instance, new TestMetricsLogger());

                var builder = AspNetCore.WebHost.CreateDefaultBuilder()
                              .UseStartup <Startup>()
                              .ConfigureServices(services =>
                {
                    services.Replace(new ServiceDescriptor(typeof(IOptions <ScriptApplicationHostOptions>), new OptionsWrapper <ScriptApplicationHostOptions>(HostOptions)));
                    services.Replace(new ServiceDescriptor(typeof(ISecretManagerProvider), new TestSecretManagerProvider(new TestSecretManager())));
                    services.Replace(new ServiceDescriptor(typeof(IOptionsMonitor <ScriptApplicationHostOptions>), optionsMonitor));
                    services.Replace(new ServiceDescriptor(typeof(IFunctionMetadataProvider), provider));

                    services.SkipDependencyValidation();
                });

                // TODO: https://github.com/Azure/azure-functions-host/issues/4876
                _testServer = new TestServer(builder);
                HostOptions.RootServiceProvider = _testServer.Host.Services;
                var scriptConfig = _testServer.Host.Services.GetService <IOptions <ScriptJobHostOptions> >().Value;

                HttpClient             = _testServer.CreateClient();
                HttpClient.BaseAddress = new Uri("https://localhost/");

                TestHelpers.WaitForWebHost(HttpClient);
            }
Beispiel #7
0
        public void ValidateFunctionName_ThrowsOnInvalidName(string functionName)
        {
            string functionsPath = "c:\testdir";

            _scriptApplicationHostOptions.ScriptPath = functionsPath;
            var optionsMonitor   = TestHelpers.CreateOptionsMonitor(_scriptApplicationHostOptions);
            var metadataProvider = new FunctionMetadataProvider(optionsMonitor, NullLogger <FunctionMetadataProvider> .Instance, _testMetricsLogger);

            var ex = Assert.Throws <InvalidOperationException>(() =>
            {
                metadataProvider.ValidateName(functionName);
            });

            Assert.Equal(string.Format("'{0}' is not a valid function name.", functionName), ex.Message);
        }
Beispiel #8
0
        public void ValidateFunctionName_DoesNotThrowOnValidName(string functionName)
        {
            string functionsPath = "c:\testdir";

            _scriptApplicationHostOptions.ScriptPath = functionsPath;
            var optionsMonitor   = TestHelpers.CreateOptionsMonitor(_scriptApplicationHostOptions);
            var metadataProvider = new FunctionMetadataProvider(optionsMonitor, NullLogger <FunctionMetadataProvider> .Instance, _testMetricsLogger);

            try
            {
                metadataProvider.ValidateName(functionName);
            }
            catch (InvalidOperationException)
            {
                Assert.True(false, $"Valid function name {functionName} failed validation.");
            }
        }
        public void ReadFunctionMetadata_Succeeds()
        {
            string functionsPath = Path.Combine(Environment.CurrentDirectory, @"..\..\..\..\..\sample\node");
            var    scriptApplicationHostOptions = new ScriptApplicationHostOptions()
            {
                ScriptPath = functionsPath
            };

            var optionsMonitor = TestHelpers.CreateOptionsMonitor(scriptApplicationHostOptions);
            var workerOptions  = new LanguageWorkerOptions
            {
                WorkerConfigs = TestHelpers.GetTestWorkerConfigs()
            };

            var metadataProvider = new FunctionMetadataProvider(optionsMonitor, new OptionsWrapper <LanguageWorkerOptions>(workerOptions), NullLogger <FunctionMetadataProvider> .Instance);

            Assert.Equal(17, metadataProvider.GetFunctionMetadata(false).Length);
        }
Beispiel #10
0
            public TestFixture()
            {
                // copy test files to temp directory, since accessing the metadata APIs will result
                // in file creations (for test data files)
                var scriptSource = Path.Combine(Environment.CurrentDirectory, @"..\..\..\TestScripts\Proxies");

                _testHome = Path.Combine(Path.GetTempPath(), @"ProxyTests");
                var scriptRoot = Path.Combine(_testHome, @"site\wwwroot");

                FileUtility.CopyDirectory(scriptSource, scriptRoot);

                HostOptions = new ScriptApplicationHostOptions
                {
                    IsSelfHost   = true,
                    ScriptPath   = scriptRoot,
                    LogPath      = Path.Combine(_testHome, @"LogFiles\Application\Functions"),
                    SecretsPath  = Path.Combine(_testHome, @"data\Functions\Secrets"),
                    TestDataPath = Path.Combine(_testHome, @"data\Functions\SampleData")
                };

                FileUtility.EnsureDirectoryExists(HostOptions.TestDataPath);

                var optionsMonitor = TestHelpers.CreateOptionsMonitor(HostOptions);

                var builder = AspNetCore.WebHost.CreateDefaultBuilder()
                              .UseStartup <Startup>()
                              .ConfigureServices(services =>
                {
                    services.Replace(new ServiceDescriptor(typeof(IOptions <ScriptApplicationHostOptions>), new OptionsWrapper <ScriptApplicationHostOptions>(HostOptions)));
                    services.Replace(new ServiceDescriptor(typeof(ISecretManagerProvider), new TestSecretManagerProvider(new TestSecretManager())));
                    services.Replace(new ServiceDescriptor(typeof(IOptionsMonitor <ScriptApplicationHostOptions>), optionsMonitor));
                });

                _testServer = new TestServer(builder);

                var scriptConfig = _testServer.Host.Services.GetService <IOptions <ScriptJobHostOptions> >().Value;

                HttpClient             = _testServer.CreateClient();
                HttpClient.BaseAddress = new Uri("https://localhost/");

                TestHelpers.WaitForWebHost(HttpClient);
            }
        public TestFunctionHost(string scriptPath, string logPath,
                                Action <IServiceCollection> configureWebHostServices               = null,
                                Action <IWebJobsBuilder> configureScriptHostWebJobsBuilder         = null,
                                Action <IConfigurationBuilder> configureScriptHostAppConfiguration = null,
                                Action <ILoggingBuilder> configureScriptHostLogging     = null,
                                Action <IServiceCollection> configureScriptHostServices = null)
        {
            _appRoot = scriptPath;

            _hostOptions = new ScriptApplicationHostOptions
            {
                IsSelfHost     = true,
                ScriptPath     = _appRoot,
                LogPath        = logPath,
                SecretsPath    = Environment.CurrentDirectory, // not used
                HasParentScope = true
            };

            var optionsMonitor  = TestHelpers.CreateOptionsMonitor(_hostOptions);
            var serviceProvider = new TestServiceProvider(_hostOptions, optionsMonitor);

            _hostOptions.RootServiceProvider = serviceProvider;

            var builder = new WebHostBuilder()
                          .ConfigureLogging(b =>
            {
                b.AddProvider(_webHostLoggerProvider);
            })
                          .ConfigureServices(services =>
            {
                services.Replace(new ServiceDescriptor(typeof(ISecretManagerProvider), new TestSecretManagerProvider(new TestSecretManager())));
                services.Replace(ServiceDescriptor.Singleton <IServiceProviderFactory <IServiceCollection> >(new WebHostServiceProviderFactory()));
                services.Replace(new ServiceDescriptor(typeof(IOptions <ScriptApplicationHostOptions>), new OptionsWrapper <ScriptApplicationHostOptions>(_hostOptions)));
                services.Replace(new ServiceDescriptor(typeof(IOptionsMonitor <ScriptApplicationHostOptions>), optionsMonitor));
                services.Replace(new ServiceDescriptor(typeof(IExtensionBundleManager), new TestExtensionBundleManager()));


                // Allows us to configure services as the last step, thereby overriding anything
                services.AddSingleton(new PostConfigureServices(configureWebHostServices));
            })
                          .ConfigureScriptHostWebJobsBuilder(scriptHostWebJobsBuilder =>
            {
                scriptHostWebJobsBuilder.AddAzureStorage();
                configureScriptHostWebJobsBuilder?.Invoke(scriptHostWebJobsBuilder);
            })
                          .ConfigureScriptHostAppConfiguration(scriptHostConfigurationBuilder =>
            {
                scriptHostConfigurationBuilder.AddTestSettings();
                configureScriptHostAppConfiguration?.Invoke(scriptHostConfigurationBuilder);
            })
                          .ConfigureScriptHostLogging(scriptHostLoggingBuilder =>
            {
                scriptHostLoggingBuilder.AddProvider(_scriptHostLoggerProvider);
                scriptHostLoggingBuilder.AddFilter <TestLoggerProvider>(_ => true);
                configureScriptHostLogging?.Invoke(scriptHostLoggingBuilder);
            })
                          .ConfigureScriptHostServices(scriptHostServices =>
            {
                configureScriptHostServices?.Invoke(scriptHostServices);
            })
                          .UseStartup <TestStartup>();

            _testServer = new TestServer(builder);

            HttpClient = new HttpClient(new UpdateContentLengthHandler(_testServer.CreateHandler()))
            {
                BaseAddress = new Uri("https://localhost/")
            };

            var manager = _testServer.Host.Services.GetService <IScriptHostManager>();

            _hostService = manager as WebJobsScriptHostService;
            StartAsync().GetAwaiter().GetResult();
        }
Beispiel #12
0
        public TestFunctionHost(string scriptPath, string logPath,
                                Action <IServiceCollection> configureWebHostServices               = null,
                                Action <IWebJobsBuilder> configureScriptHostWebJobsBuilder         = null,
                                Action <IConfigurationBuilder> configureScriptHostAppConfiguration = null,
                                Action <ILoggingBuilder> configureScriptHostLogging     = null,
                                Action <IServiceCollection> configureScriptHostServices = null)
        {
            _appRoot = scriptPath;

            _hostOptions = new ScriptApplicationHostOptions
            {
                IsSelfHost     = true,
                ScriptPath     = _appRoot,
                LogPath        = logPath,
                SecretsPath    = Environment.CurrentDirectory, // not used
                HasParentScope = true
            };

            var builder = new WebHostBuilder()
                          .ConfigureLogging(b =>
            {
                b.AddProvider(_webHostLoggerProvider);
            })
                          .ConfigureServices(services =>
            {
                services.Replace(new ServiceDescriptor(typeof(ISecretManagerProvider), new TestSecretManagerProvider(new TestSecretManager())));
                services.Replace(ServiceDescriptor.Singleton <IServiceProviderFactory <IServiceCollection> >(new WebHostServiceProviderFactory()));
                services.Replace(new ServiceDescriptor(typeof(IOptions <ScriptApplicationHostOptions>), sp =>
                {
                    _hostOptions.RootServiceProvider = sp;
                    return(new OptionsWrapper <ScriptApplicationHostOptions>(_hostOptions));
                }, ServiceLifetime.Singleton));
                services.Replace(new ServiceDescriptor(typeof(IOptionsMonitor <ScriptApplicationHostOptions>), sp =>
                {
                    _hostOptions.RootServiceProvider = sp;
                    return(TestHelpers.CreateOptionsMonitor(_hostOptions));
                }, ServiceLifetime.Singleton));
                services.Replace(new ServiceDescriptor(typeof(IExtensionBundleManager), new TestExtensionBundleManager()));
                services.Replace(new ServiceDescriptor(typeof(IFunctionMetadataManager), sp =>
                {
                    var montior       = sp.GetService <IOptionsMonitor <ScriptApplicationHostOptions> >();
                    var scriptManager = sp.GetService <IScriptHostManager>();
                    var loggerFactory = sp.GetService <ILoggerFactory>();

                    return(GetMetadataManager(montior, scriptManager, loggerFactory));
                }, ServiceLifetime.Singleton));

                // Allows us to configure services as the last step, thereby overriding anything
                services.AddSingleton(new PostConfigureServices(configureWebHostServices));
            })
                          .ConfigureScriptHostWebJobsBuilder(scriptHostWebJobsBuilder =>
            {
                scriptHostWebJobsBuilder.AddAzureStorage();
                configureScriptHostWebJobsBuilder?.Invoke(scriptHostWebJobsBuilder);
            })
                          .ConfigureScriptHostAppConfiguration(scriptHostConfigurationBuilder =>
            {
                scriptHostConfigurationBuilder.AddTestSettings();
                configureScriptHostAppConfiguration?.Invoke(scriptHostConfigurationBuilder);
            })
                          .ConfigureScriptHostLogging(scriptHostLoggingBuilder =>
            {
                scriptHostLoggingBuilder.AddProvider(_scriptHostLoggerProvider);
                scriptHostLoggingBuilder.AddFilter <TestLoggerProvider>(_ => true);
                configureScriptHostLogging?.Invoke(scriptHostLoggingBuilder);
            })
                          .ConfigureScriptHostServices(scriptHostServices =>
            {
                configureScriptHostServices?.Invoke(scriptHostServices);
            })
                          .UseStartup <TestStartup>();

            _testServer = new TestServer(builder)
            {
                BaseAddress = new Uri("https://localhost/")
            };

            HttpClient = _testServer.CreateClient();

            var manager = _testServer.Host.Services.GetService <IScriptHostManager>();

            _hostService = manager as WebJobsScriptHostService;

            // Wire up StopApplication calls as they behave in hosted scenarios
            var lifetime = WebHostServices.GetService <IApplicationLifetime>();

            lifetime.ApplicationStopping.Register(async() => await _testServer.Host.StopAsync());

            StartAsync().GetAwaiter().GetResult();
        }
Beispiel #13
0
        public TestFunctionHost(string scriptPath, string logPath,
                                Action <IServiceCollection> configureWebHostServices               = null,
                                Action <IWebJobsBuilder> configureScriptHostWebJobsBuilder         = null,
                                Action <IConfigurationBuilder> configureScriptHostAppConfiguration = null,
                                Action <ILoggingBuilder> configureScriptHostLogging     = null,
                                Action <IServiceCollection> configureScriptHostServices = null)
        {
            _appRoot = scriptPath;

            _hostOptions = new ScriptApplicationHostOptions
            {
                IsSelfHost     = true,
                ScriptPath     = _appRoot,
                LogPath        = logPath,
                SecretsPath    = Environment.CurrentDirectory, // not used
                HasParentScope = true
            };

            var builder = new WebHostBuilder()
                          .ConfigureLogging(b =>
            {
                b.AddProvider(_webHostLoggerProvider);
            })
                          .ConfigureServices(services =>
            {
                services.Replace(new ServiceDescriptor(typeof(ISecretManagerProvider), new TestSecretManagerProvider(new TestSecretManager())));
                services.Replace(ServiceDescriptor.Singleton <IServiceProviderFactory <IServiceCollection> >(new WebHostServiceProviderFactory()));
                services.Replace(new ServiceDescriptor(typeof(IOptions <ScriptApplicationHostOptions>), sp =>
                {
                    _hostOptions.RootServiceProvider = sp;
                    return(new OptionsWrapper <ScriptApplicationHostOptions>(_hostOptions));
                }, ServiceLifetime.Singleton));
                services.Replace(new ServiceDescriptor(typeof(IOptionsMonitor <ScriptApplicationHostOptions>), sp =>
                {
                    _hostOptions.RootServiceProvider = sp;
                    return(TestHelpers.CreateOptionsMonitor(_hostOptions));
                }, ServiceLifetime.Singleton));
                services.Replace(new ServiceDescriptor(typeof(IExtensionBundleManager), new TestExtensionBundleManager()));
                services.Replace(new ServiceDescriptor(typeof(IFunctionMetadataManager), sp =>
                {
                    var montior       = sp.GetService <IOptionsMonitor <ScriptApplicationHostOptions> >();
                    var scriptManager = sp.GetService <IScriptHostManager>();
                    var loggerFactory = sp.GetService <ILoggerFactory>();
                    var environment   = sp.GetService <IEnvironment>();

                    return(GetMetadataManager(montior, scriptManager, loggerFactory, environment));
                }, ServiceLifetime.Singleton));

                services.SkipDependencyValidation();

                // Allows us to configure services as the last step, thereby overriding anything
                services.AddSingleton(new PostConfigureServices(configureWebHostServices));
            })
                          .ConfigureScriptHostWebJobsBuilder(scriptHostWebJobsBuilder =>
            {
                /// REVIEW THIS
                scriptHostWebJobsBuilder.AddAzureStorage();
                configureScriptHostWebJobsBuilder?.Invoke(scriptHostWebJobsBuilder);
            })
                          .ConfigureScriptHostAppConfiguration(scriptHostConfigurationBuilder =>
            {
                scriptHostConfigurationBuilder.AddTestSettings();
                configureScriptHostAppConfiguration?.Invoke(scriptHostConfigurationBuilder);
            })
                          .ConfigureScriptHostLogging(scriptHostLoggingBuilder =>
            {
                scriptHostLoggingBuilder.AddProvider(_scriptHostLoggerProvider);
                scriptHostLoggingBuilder.AddFilter <TestLoggerProvider>(_ => true);
                configureScriptHostLogging?.Invoke(scriptHostLoggingBuilder);
            })
                          .ConfigureScriptHostServices(scriptHostServices =>
            {
                configureScriptHostServices?.Invoke(scriptHostServices);
            })
                          .ConfigureAppConfiguration((builderContext, config) =>
            {
                // replace the default environment source with our own
                IConfigurationSource envVarsSource = config.Sources.OfType <EnvironmentVariablesConfigurationSource>().FirstOrDefault();
                if (envVarsSource != null)
                {
                    config.Sources.Remove(envVarsSource);
                }

                config.Add(new ScriptEnvironmentVariablesConfigurationSource());
                config.AddTestSettings();
            })
                          .UseStartup <TestStartup>();

            _testServer = new TestServer(builder)
            {
                BaseAddress = new Uri("https://localhost/")
            };

            HttpClient         = _testServer.CreateClient();
            HttpClient.Timeout = TimeSpan.FromMinutes(5);

            var manager = _testServer.Host.Services.GetService <IScriptHostManager>();

            _hostService = manager as WebJobsScriptHostService;

            // Wire up StopApplication calls as they behave in hosted scenarios
            var lifetime = WebHostServices.GetService <IApplicationLifetime>();

            lifetime.ApplicationStopping.Register(async() => await _testServer.Host.StopAsync());

            StartAsync().GetAwaiter().GetResult();

            _stillRunningTimer = new Timer(StillRunningCallback, _testServer, TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(30));

            // store off a bit of the creation stack for easier debugging if this host doesn't shut down.
            var stack = new StackTrace(true).ToString().Split(Environment.NewLine).Take(5);

            _createdStack = string.Join($"{Environment.NewLine}    ", stack);

            // cache startup logs since tests clear logs from time to time
            StartupLogs = GetScriptHostLogMessages();
        }