From 70495faaf27e305df2452e52307e62de6cb62a42 Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Fri, 27 Jul 2018 18:52:53 -0700 Subject: [PATCH] Fixing tests. Renaming DI types to have consistent terminology. --- sample/host.json | 2 +- .../Configuration/ScriptHostOptionsSetup.cs | 3 + ...HostLifetime.cs => JobHostHostLifetime.cs} | 2 +- ...=> JobHostScopedServiceProviderFactory.cs} | 10 +- ...eProvider.cs => JobHostServiceProvider.cs} | 12 +- ...ServiceScope.cs => JobHostServiceScope.cs} | 4 +- ...ostScopedResolver.cs => ScopedResolver.cs} | 12 +- ...iptHostServiceScope.cs => ServiceScope.cs} | 4 +- ...eProvider.cs => WebHostServiceProvider.cs} | 12 +- ...ry.cs => WebHostServiceProviderFactory.cs} | 4 +- .../FunctionInvocationMiddleware.cs | 11 +- src/WebJobs.Script.WebHost/Program.cs | 2 +- .../ScriptHostBuilderExtensions.cs | 57 ++++- ... => WebHostServiceCollectionExtensions.cs} | 4 +- .../WebJobsApplicationBuilderExtension.cs | 2 +- .../WebJobsScriptHostService.cs | 50 +--- .../Config/ScriptHostOptions.cs | 2 + .../PrimaryHostCoordinatorTests.cs | 11 +- .../TestHostBuilderExtensions.cs | 34 ++- .../ScriptHostOptionsSetupTests.cs | 92 ++++++++ .../WebScriptHostConfigurationSourceTests.cs | 13 ++ .../FunctionMetadataManagerTests.cs | 204 +++++++++++++++++ test/WebJobs.Script.Tests/ScriptHostTests.cs | 216 +----------------- 23 files changed, 456 insertions(+), 307 deletions(-) rename src/WebJobs.Script.WebHost/DependencyInjection/{ScriptHostLifetime.cs => JobHostHostLifetime.cs} (91%) rename src/WebJobs.Script.WebHost/DependencyInjection/{ScriptHostScopedServiceProviderFactory.cs => JobHostScopedServiceProviderFactory.cs} (68%) rename src/WebJobs.Script.WebHost/DependencyInjection/{ScriptHostServiceProvider.cs => JobHostServiceProvider.cs} (87%) rename src/WebJobs.Script.WebHost/DependencyInjection/{FunctionsServiceScope.cs => JobHostServiceScope.cs} (83%) rename src/WebJobs.Script.WebHost/DependencyInjection/{ScriptHostScopedResolver.cs => ScopedResolver.cs} (79%) rename src/WebJobs.Script.WebHost/DependencyInjection/{ScriptHostServiceScope.cs => ServiceScope.cs} (86%) rename src/WebJobs.Script.WebHost/DependencyInjection/{FunctionsServiceProvider.cs => WebHostServiceProvider.cs} (77%) rename src/WebJobs.Script.WebHost/DependencyInjection/{FunctionsServiceProviderFactory.cs => WebHostServiceProviderFactory.cs} (77%) rename src/WebJobs.Script.WebHost/{WebJobsServiceCollectionExtensions.cs => WebHostServiceCollectionExtensions.cs} (98%) create mode 100644 test/WebJobs.Script.Tests/Configuration/ScriptHostOptionsSetupTests.cs create mode 100644 test/WebJobs.Script.Tests/Configuration/WebScriptHostConfigurationSourceTests.cs create mode 100644 test/WebJobs.Script.Tests/FunctionMetadataManagerTests.cs diff --git a/sample/host.json b/sample/host.json index 73d7f3bb2c..0e3343dd32 100644 --- a/sample/host.json +++ b/sample/host.json @@ -1,5 +1,5 @@ { - "watchDirectories": [ "Shared" ], + "watchDirectories": [ "Shared", "Test" ], "sendGrid": { "from": "Azure Functions " }, diff --git a/src/WebJobs.Script.WebHost/Configuration/ScriptHostOptionsSetup.cs b/src/WebJobs.Script.WebHost/Configuration/ScriptHostOptionsSetup.cs index dfb85ade28..ad003b7413 100644 --- a/src/WebJobs.Script.WebHost/Configuration/ScriptHostOptionsSetup.cs +++ b/src/WebJobs.Script.WebHost/Configuration/ScriptHostOptionsSetup.cs @@ -20,6 +20,9 @@ public ScriptHostOptionsSetup(IConfiguration configuration, IOptions /// An implementation that creates - /// and populates an that can be used as the + /// and populates an that can be used as the /// - public class ScriptHostScopedServiceProviderFactory : IServiceProviderFactory + public class JobHostScopedServiceProviderFactory : IServiceProviderFactory { private readonly IServiceProvider _rootProvider; private readonly IServiceScopeFactory _rootScopeFactory; - private ScriptHostServiceProvider _provider; + private JobHostServiceProvider _provider; - public ScriptHostScopedServiceProviderFactory(IServiceProvider rootProvider, IServiceScopeFactory rootScopeFactory) + public JobHostScopedServiceProviderFactory(IServiceProvider rootProvider, IServiceScopeFactory rootScopeFactory) { _rootProvider = rootProvider ?? throw new ArgumentNullException(nameof(rootProvider)); _rootScopeFactory = rootScopeFactory ?? throw new ArgumentNullException(nameof(rootScopeFactory)); @@ -31,7 +31,7 @@ public IServiceProvider CreateServiceProvider(IServiceCollection containerBuilde { if (_provider == null) { - _provider = new ScriptHostServiceProvider(containerBuilder, _rootProvider, _rootScopeFactory); + _provider = new JobHostServiceProvider(containerBuilder, _rootProvider, _rootScopeFactory); } return _provider; diff --git a/src/WebJobs.Script.WebHost/DependencyInjection/ScriptHostServiceProvider.cs b/src/WebJobs.Script.WebHost/DependencyInjection/JobHostServiceProvider.cs similarity index 87% rename from src/WebJobs.Script.WebHost/DependencyInjection/ScriptHostServiceProvider.cs rename to src/WebJobs.Script.WebHost/DependencyInjection/JobHostServiceProvider.cs index 876c70d292..0557b35067 100644 --- a/src/WebJobs.Script.WebHost/DependencyInjection/ScriptHostServiceProvider.cs +++ b/src/WebJobs.Script.WebHost/DependencyInjection/JobHostServiceProvider.cs @@ -13,7 +13,7 @@ namespace Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection { - public class ScriptHostServiceProvider : IServiceProvider, IServiceScopeFactory, ISupportRequiredService, IDisposable + public class JobHostServiceProvider : IServiceProvider, IServiceScopeFactory, ISupportRequiredService, IDisposable { private const string ScriptJobHostScope = "scriptjobhost"; @@ -21,9 +21,9 @@ public class ScriptHostServiceProvider : IServiceProvider, IServiceScopeFactory, private readonly IServiceProvider _rootProvider; private readonly IServiceScopeFactory _rootScopeFactory; private readonly Container _container; - private ScriptHostScopedResolver _currentResolver; + private ScopedResolver _currentResolver; - static ScriptHostServiceProvider() + static JobHostServiceProvider() { _defaultContainerRules = Rules.Default .With(FactoryMethod.ConstructorWithResolvableArguments) @@ -31,7 +31,7 @@ static ScriptHostServiceProvider() .WithTrackingDisposableTransients(); } - public ScriptHostServiceProvider(IServiceCollection descriptors, IServiceProvider rootProvider, IServiceScopeFactory rootScopeFactory) + public JobHostServiceProvider(IServiceCollection descriptors, IServiceProvider rootProvider, IServiceScopeFactory rootScopeFactory) { if (descriptors == null) { @@ -42,7 +42,7 @@ public ScriptHostServiceProvider(IServiceCollection descriptors, IServiceProvide _rootScopeFactory = rootScopeFactory ?? throw new ArgumentNullException(nameof(rootScopeFactory)); _container = BuildContainer(descriptors); - _currentResolver = new ScriptHostScopedResolver(_container); + _currentResolver = new ScopedResolver(_container); } public IServiceProvider ServiceProvider => throw new NotImplementedException(); @@ -64,7 +64,7 @@ private Container BuildContainer(IServiceCollection descriptors) container.Populate(descriptors); container.UseInstance(this); - container.UseInstance(this); + container.UseInstance(this); return container; } diff --git a/src/WebJobs.Script.WebHost/DependencyInjection/FunctionsServiceScope.cs b/src/WebJobs.Script.WebHost/DependencyInjection/JobHostServiceScope.cs similarity index 83% rename from src/WebJobs.Script.WebHost/DependencyInjection/FunctionsServiceScope.cs rename to src/WebJobs.Script.WebHost/DependencyInjection/JobHostServiceScope.cs index 18c4f47658..c7f8ab6b47 100644 --- a/src/WebJobs.Script.WebHost/DependencyInjection/FunctionsServiceScope.cs +++ b/src/WebJobs.Script.WebHost/DependencyInjection/JobHostServiceScope.cs @@ -7,11 +7,11 @@ namespace Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection { - public class FunctionsServiceScope : IServiceScope + public class JobHostServiceScope : IServiceScope { private readonly ScopedServiceProvider _serviceProvider; - public FunctionsServiceScope(IResolverContext serviceProvider) + public JobHostServiceScope(IResolverContext serviceProvider) { _serviceProvider = new ScopedServiceProvider(serviceProvider); } diff --git a/src/WebJobs.Script.WebHost/DependencyInjection/ScriptHostScopedResolver.cs b/src/WebJobs.Script.WebHost/DependencyInjection/ScopedResolver.cs similarity index 79% rename from src/WebJobs.Script.WebHost/DependencyInjection/ScriptHostScopedResolver.cs rename to src/WebJobs.Script.WebHost/DependencyInjection/ScopedResolver.cs index 131b387d0c..3e62978403 100644 --- a/src/WebJobs.Script.WebHost/DependencyInjection/ScriptHostScopedResolver.cs +++ b/src/WebJobs.Script.WebHost/DependencyInjection/ScopedResolver.cs @@ -10,18 +10,18 @@ namespace Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection { - internal class ScriptHostScopedResolver : IDisposable + internal class ScopedResolver : IDisposable { - public ScriptHostScopedResolver(IContainer resolver, bool isRootResolver = false) + public ScopedResolver(IContainer resolver, bool isRootResolver = false) { Container = resolver ?? throw new ArgumentNullException(nameof(resolver)); IsRootResolver = isRootResolver; - ChildScopes = new HashSet(); + ChildScopes = new HashSet(); } public IContainer Container { get; } - public HashSet ChildScopes { get; } + public HashSet ChildScopes { get; } public bool IsRootResolver { get; } @@ -35,7 +35,7 @@ public void Dispose() }); } - internal ScriptHostServiceScope CreateChildScope(IServiceScopeFactory rootScopeFactory) + internal ServiceScope CreateChildScope(IServiceScopeFactory rootScopeFactory) { var scopedRoot = rootScopeFactory.CreateScope(); Container scopedContext = Container.OpenScope() as Container; @@ -51,7 +51,7 @@ internal ScriptHostServiceScope CreateChildScope(IServiceScopeFactory rootScopeF return new DelegateFactory(_ => scopedRoot.ServiceProvider.GetService(request.ServiceType)); })); - var scope = new ScriptHostServiceScope(resolver, scopedRoot); + var scope = new ServiceScope(resolver, scopedRoot); ChildScopes.Add(scope); scope.DisposalTask.ContinueWith(t => ChildScopes.Remove(scope)); diff --git a/src/WebJobs.Script.WebHost/DependencyInjection/ScriptHostServiceScope.cs b/src/WebJobs.Script.WebHost/DependencyInjection/ServiceScope.cs similarity index 86% rename from src/WebJobs.Script.WebHost/DependencyInjection/ScriptHostServiceScope.cs rename to src/WebJobs.Script.WebHost/DependencyInjection/ServiceScope.cs index 90bedc3b03..9b6325dc91 100644 --- a/src/WebJobs.Script.WebHost/DependencyInjection/ScriptHostServiceScope.cs +++ b/src/WebJobs.Script.WebHost/DependencyInjection/ServiceScope.cs @@ -8,13 +8,13 @@ namespace Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection { - public class ScriptHostServiceScope : IServiceScope + public class ServiceScope : IServiceScope { private readonly TaskCompletionSource _activeTcs; private readonly ScopedServiceProvider _serviceProvider; private readonly IServiceScope _rootScope; - public ScriptHostServiceScope(IResolverContext serviceProvider, IServiceScope rootScope) + public ServiceScope(IResolverContext serviceProvider, IServiceScope rootScope) { _activeTcs = new TaskCompletionSource(); _serviceProvider = new ScopedServiceProvider(serviceProvider); diff --git a/src/WebJobs.Script.WebHost/DependencyInjection/FunctionsServiceProvider.cs b/src/WebJobs.Script.WebHost/DependencyInjection/WebHostServiceProvider.cs similarity index 77% rename from src/WebJobs.Script.WebHost/DependencyInjection/FunctionsServiceProvider.cs rename to src/WebJobs.Script.WebHost/DependencyInjection/WebHostServiceProvider.cs index fc75a8f091..ce70aa1ac4 100644 --- a/src/WebJobs.Script.WebHost/DependencyInjection/FunctionsServiceProvider.cs +++ b/src/WebJobs.Script.WebHost/DependencyInjection/WebHostServiceProvider.cs @@ -8,13 +8,13 @@ namespace Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection { - public class FunctionsServiceProvider : IServiceProvider, IServiceScopeFactory + public class WebHostServiceProvider : IServiceProvider, IServiceScopeFactory { private static readonly Rules _defaultContainerRules; private readonly Container _container; - private ScriptHostScopedResolver _currentResolver; + private ScopedResolver _currentResolver; - static FunctionsServiceProvider() + static WebHostServiceProvider() { _defaultContainerRules = Rules.Default .With(FactoryMethod.ConstructorWithResolvableArguments) @@ -22,7 +22,7 @@ static FunctionsServiceProvider() .WithTrackingDisposableTransients(); } - public FunctionsServiceProvider(IServiceCollection descriptors) + public WebHostServiceProvider(IServiceCollection descriptors) { if (descriptors == null) { @@ -34,7 +34,7 @@ public FunctionsServiceProvider(IServiceCollection descriptors) _container.UseInstance(this); _container.UseInstance(this); - _currentResolver = new ScriptHostScopedResolver(_container); + _currentResolver = new ScopedResolver(_container); } public object GetService(Type serviceType) @@ -44,7 +44,7 @@ public object GetService(Type serviceType) public IServiceScope CreateScope() { - return new FunctionsServiceScope(_container.OpenScope()); + return new JobHostServiceScope(_container.OpenScope()); } } } diff --git a/src/WebJobs.Script.WebHost/DependencyInjection/FunctionsServiceProviderFactory.cs b/src/WebJobs.Script.WebHost/DependencyInjection/WebHostServiceProviderFactory.cs similarity index 77% rename from src/WebJobs.Script.WebHost/DependencyInjection/FunctionsServiceProviderFactory.cs rename to src/WebJobs.Script.WebHost/DependencyInjection/WebHostServiceProviderFactory.cs index 2512bb053b..8db787bfd9 100644 --- a/src/WebJobs.Script.WebHost/DependencyInjection/FunctionsServiceProviderFactory.cs +++ b/src/WebJobs.Script.WebHost/DependencyInjection/WebHostServiceProviderFactory.cs @@ -6,7 +6,7 @@ namespace Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection { - internal class FunctionsServiceProviderFactory : IServiceProviderFactory + internal class WebHostServiceProviderFactory : IServiceProviderFactory { public IServiceCollection CreateBuilder(IServiceCollection services) { @@ -15,7 +15,7 @@ public IServiceCollection CreateBuilder(IServiceCollection services) public IServiceProvider CreateServiceProvider(IServiceCollection services) { - return new FunctionsServiceProvider(services); + return new WebHostServiceProvider(services); } } } diff --git a/src/WebJobs.Script.WebHost/Middleware/FunctionInvocationMiddleware.cs b/src/WebJobs.Script.WebHost/Middleware/FunctionInvocationMiddleware.cs index 76fd9b0f94..fd7a983c38 100644 --- a/src/WebJobs.Script.WebHost/Middleware/FunctionInvocationMiddleware.cs +++ b/src/WebJobs.Script.WebHost/Middleware/FunctionInvocationMiddleware.cs @@ -31,11 +31,14 @@ public FunctionInvocationMiddleware(RequestDelegate next) _next = next; } - public async Task Invoke(HttpContext context, IScriptJobHost scriptHost) + public async Task Invoke(HttpContext context, IScriptJobHost scriptHost = null) { - // flow required context through the request pipeline - // downstream middleware and filters rely on this - context.Items[ScriptConstants.AzureFunctionsHostKey] = scriptHost; + if (scriptHost != null) + { + // flow required context through the request pipeline + // downstream middleware and filters rely on this + context.Items[ScriptConstants.AzureFunctionsHostKey] = scriptHost; + } SetRequestId(context.Request); if (_next != null) diff --git a/src/WebJobs.Script.WebHost/Program.cs b/src/WebJobs.Script.WebHost/Program.cs index 129bf29886..3641c2f492 100644 --- a/src/WebJobs.Script.WebHost/Program.cs +++ b/src/WebJobs.Script.WebHost/Program.cs @@ -35,7 +35,7 @@ public static IWebHostBuilder CreateWebHostBuilder(string[] args = null) return Microsoft.AspNetCore.WebHost.CreateDefaultBuilder(args) .ConfigureServices(services => { - services.Replace(ServiceDescriptor.Singleton>(new FunctionsServiceProviderFactory())); + services.Replace(ServiceDescriptor.Singleton>(new WebHostServiceProviderFactory())); }) .ConfigureAppConfiguration((builderContext, config) => { diff --git a/src/WebJobs.Script.WebHost/ScriptHostBuilderExtensions.cs b/src/WebJobs.Script.WebHost/ScriptHostBuilderExtensions.cs index 79b6dd4849..42f1f37afb 100644 --- a/src/WebJobs.Script.WebHost/ScriptHostBuilderExtensions.cs +++ b/src/WebJobs.Script.WebHost/ScriptHostBuilderExtensions.cs @@ -1,25 +1,80 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. +using System; using Microsoft.Azure.WebJobs.Host.Executors; using Microsoft.Azure.WebJobs.Host.Timers; +using Microsoft.Azure.WebJobs.Hosting; using Microsoft.Azure.WebJobs.Script.Binding; using Microsoft.Azure.WebJobs.Script.BindingExtensions; using Microsoft.Azure.WebJobs.Script.Config; using Microsoft.Azure.WebJobs.Script.Diagnostics; using Microsoft.Azure.WebJobs.Script.Eventing; using Microsoft.Azure.WebJobs.Script.Extensibility; +using Microsoft.Azure.WebJobs.Script.WebHost.Configuration; using Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection; using Microsoft.Azure.WebJobs.Script.WebHost.Diagnostics; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; namespace Microsoft.Azure.WebJobs.Script.WebHost { public static class ScriptHostBuilderExtensions { - public static IHostBuilder AddScriptHost(this IHostBuilder builder, IOptions webHostOptions) + public static IHostBuilder AddScriptHost(this IHostBuilder builder, IServiceProvider rootServiceProvider, + IServiceScopeFactory rootScopeFactory, IOptions webHostOptions) + { + // Host configuration + builder.UseServiceProviderFactory(new JobHostScopedServiceProviderFactory(rootServiceProvider, rootScopeFactory)) + .ConfigureLogging(b => + { + b.AddConsole(c => { c.DisableColors = false; }); + b.SetMinimumLevel(LogLevel.Trace); + b.AddFilter(f => true); + + // TODO: DI (FACAVAL) Temporary - replace with proper logger factory using + // job host configuration + b.Services.AddSingleton(); + + b.Services.AddSingleton(); + b.Services.AddSingleton(); + b.Services.AddSingleton(); + }) + .ConfigureServices(s => + { + s.AddSingleton(); + }) + .ConfigureAppConfiguration(c => + { + c.Add(new HostJsonFileConfigurationSource(webHostOptions)); + }); + + // WebJobs configuration + builder.AddScriptHostCore(webHostOptions); + + // HACK: Remove previous IHostedService registration + // TODO: DI (FACAVAL) Remove this and move HttpInitialization to webjobs configuration + builder.ConfigureServices(s => + { + s.RemoveAll(); + s.TryAddEnumerable(ServiceDescriptor.Singleton()); + s.TryAddEnumerable(ServiceDescriptor.Singleton()); + s.TryAddEnumerable(ServiceDescriptor.Singleton()); + s.TryAddEnumerable(ServiceDescriptor.Singleton()); + }); + + // If there is a script host builder registered, allow it to configure + // the host builder + var scriptBuilder = rootServiceProvider.GetService(); + scriptBuilder?.Configure(builder); + + return builder; + } + + public static IHostBuilder AddScriptHostCore(this IHostBuilder builder, IOptions webHostOptions) { builder.ConfigureWebJobsHost(o => { diff --git a/src/WebJobs.Script.WebHost/WebJobsServiceCollectionExtensions.cs b/src/WebJobs.Script.WebHost/WebHostServiceCollectionExtensions.cs similarity index 98% rename from src/WebJobs.Script.WebHost/WebJobsServiceCollectionExtensions.cs rename to src/WebJobs.Script.WebHost/WebHostServiceCollectionExtensions.cs index 968c4db2e6..bcb3d156f0 100644 --- a/src/WebJobs.Script.WebHost/WebJobsServiceCollectionExtensions.cs +++ b/src/WebJobs.Script.WebHost/WebHostServiceCollectionExtensions.cs @@ -33,7 +33,7 @@ namespace Microsoft.Azure.WebJobs.Script.WebHost { - public static class WebJobsServiceCollectionExtensions + public static class WebHostServiceCollectionExtensions { public static IServiceCollection AddWebJobsScriptHostRouting(this IServiceCollection services) { @@ -124,7 +124,7 @@ public static void AddWebJobsScriptHost(this IServiceCollection services, IConfi // Configuration services.TryAddEnumerable(ServiceDescriptor.Transient, ScriptWebHostOptionsSetup>()); - } + } // TODO: DI (FACAVAL) Removing this. We need to ensure system logs are properly written now when using the default provider. //private static ILoggerFactory CreateLoggerFactory(string hostInstanceId, ScriptSettingsManager settingsManager, IEventGenerator eventGenerator, WebHostSettings settings) diff --git a/src/WebJobs.Script.WebHost/WebJobsApplicationBuilderExtension.cs b/src/WebJobs.Script.WebHost/WebJobsApplicationBuilderExtension.cs index 51ffa1f144..9c0e0d0c37 100644 --- a/src/WebJobs.Script.WebHost/WebJobsApplicationBuilderExtension.cs +++ b/src/WebJobs.Script.WebHost/WebJobsApplicationBuilderExtension.cs @@ -31,7 +31,7 @@ public static IApplicationBuilder UseWebJobsScriptHost(this IApplicationBuilder builder.UseMiddleware(); builder.UseMiddleware(); builder.UseMiddleware(); - // builder.UseMiddleware(); + builder.UseMiddleware(); builder.UseMiddleware(); builder.UseWhen(context => !context.Request.Path.StartsWithSegments("/admin"), config => diff --git a/src/WebJobs.Script.WebHost/WebJobsScriptHostService.cs b/src/WebJobs.Script.WebHost/WebJobsScriptHostService.cs index e2cf480405..3f34235a4c 100644 --- a/src/WebJobs.Script.WebHost/WebJobsScriptHostService.cs +++ b/src/WebJobs.Script.WebHost/WebJobsScriptHostService.cs @@ -171,53 +171,9 @@ public async Task RestartHostAsync(CancellationToken cancellationToken) private IHost BuildHost() { - var builder = new HostBuilder(); - - // Host configuration - builder.UseServiceProviderFactory(new ScriptHostScopedServiceProviderFactory(_rootServiceProvider, _rootScopeFactory)) - .ConfigureLogging(b => - { - b.AddConsole(c => { c.DisableColors = false; }); - b.SetMinimumLevel(LogLevel.Trace); - b.AddFilter(f => true); - - // TODO: DI (FACAVAL) Temporary - replace with proper logger factory using - // job host configuration - b.Services.AddSingleton(); - - b.Services.AddSingleton(); - b.Services.AddSingleton(); - b.Services.AddSingleton(); - }) - .ConfigureServices(s => - { - s.AddSingleton(); - }) - .ConfigureAppConfiguration(c => - { - c.Add(new HostJsonFileConfigurationSource(_webHostOptions)); - }); - - // WebJobs configuration - builder.AddScriptHost(_webHostOptions); - - // HACK: Remove previous IHostedService registration - // TODO: DI (FACAVAL) Remove this and move HttpInitialization to webjobs configuration - builder.ConfigureServices(s => - { - s.RemoveAll(); - s.TryAddEnumerable(ServiceDescriptor.Singleton()); - s.TryAddEnumerable(ServiceDescriptor.Singleton()); - s.TryAddEnumerable(ServiceDescriptor.Singleton()); - s.TryAddEnumerable(ServiceDescriptor.Singleton()); - }); - - // If there is a script host builder registered, allow it to configure - // the host builder - var scriptBuilder = _rootServiceProvider.GetService(); - scriptBuilder?.Configure(builder); - - return builder.Build(); + return new HostBuilder() + .AddScriptHost(_rootServiceProvider, _rootScopeFactory, _webHostOptions) + .Build(); } /// diff --git a/src/WebJobs.Script/Config/ScriptHostOptions.cs b/src/WebJobs.Script/Config/ScriptHostOptions.cs index e212d1e6d4..cba3937744 100644 --- a/src/WebJobs.Script/Config/ScriptHostOptions.cs +++ b/src/WebJobs.Script/Config/ScriptHostOptions.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Collections.ObjectModel; using System.IO; using Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel.Implementation; using Microsoft.Azure.WebJobs.Logging; @@ -22,6 +23,7 @@ public ScriptHostOptions() LogFilter = new LogCategoryFilter(); HostHealthMonitor = new HostHealthMonitorConfiguration(); InstanceId = Guid.NewGuid().ToString(); + WatchDirectories = new Collection(); } /// diff --git a/test/WebJobs.Script.Tests.Integration/PrimaryHostCoordinatorTests.cs b/test/WebJobs.Script.Tests.Integration/PrimaryHostCoordinatorTests.cs index 22b58f6193..85f29f9881 100644 --- a/test/WebJobs.Script.Tests.Integration/PrimaryHostCoordinatorTests.cs +++ b/test/WebJobs.Script.Tests.Integration/PrimaryHostCoordinatorTests.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using Microsoft.Azure.WebJobs.Host; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.WebJobs.Script.Tests; @@ -32,7 +33,15 @@ public PrimaryHostCoordinatorTests() private static IHost CreateHost() { var host = new HostBuilder() - .ConfigureDefaultTestScriptHost(o => o.ScriptPath = Path.GetTempPath()) + .ConfigureDefaultTestScriptHost(o => + { + o.ScriptPath = Path.GetTempPath(); + o.LogPath = Path.GetTempPath(); + }) + .ConfigureServices(s => + { + s.TryAddEnumerable(ServiceDescriptor.Singleton()); + }) .Build(); return host; diff --git a/test/WebJobs.Script.Tests.Shared/TestHostBuilderExtensions.cs b/test/WebJobs.Script.Tests.Shared/TestHostBuilderExtensions.cs index cc9d4ddfa0..f02e5d6f01 100644 --- a/test/WebJobs.Script.Tests.Shared/TestHostBuilderExtensions.cs +++ b/test/WebJobs.Script.Tests.Shared/TestHostBuilderExtensions.cs @@ -2,8 +2,13 @@ // Licensed under the MIT License. See License.txt in the project root for license information. using System; +using Microsoft.Azure.WebJobs.Extensions.Http; +using Microsoft.Azure.WebJobs.Script; using Microsoft.Azure.WebJobs.Script.WebHost; +using Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection; +using Microsoft.Azure.WebJobs.Script.WebHost.Diagnostics; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; using Moq; @@ -12,17 +17,36 @@ namespace Microsoft.WebJobs.Script.Tests { public static class TestHostBuilderExtensions { - public static IHostBuilder ConfigureDefaultTestScriptHost(this IHostBuilder builder, Action configure = null) + public static IHostBuilder ConfigureDefaultTestScriptHost(this IHostBuilder builder, Action configure = null, bool runStartupHostedServices = false) { var webHostOptions = new ScriptWebHostOptions(); configure?.Invoke(webHostOptions); - var lifetime = new Mock(); + // Register root services + var services = new ServiceCollection(); + AddMockedSingleton(services); + AddMockedSingleton(services); + AddMockedSingleton(services); + AddMockedSingleton(services); + AddMockedSingleton(services); - return builder - .ConfigureServices(s => s.AddSingleton(lifetime.Object)) - .AddScriptHost(new OptionsWrapper(webHostOptions)); + var rootProvider = new WebHostServiceProvider(services); + + builder.AddScriptHost(rootProvider, rootProvider, new OptionsWrapper(webHostOptions)); + + if (!runStartupHostedServices) + { + builder.ConfigureServices(s => s.RemoveAll()); + } + + return builder; + } + + private static IServiceCollection AddMockedSingleton(IServiceCollection services) where T : class + { + var mock = new Mock(); + return services.AddSingleton(mock.Object); } } } diff --git a/test/WebJobs.Script.Tests/Configuration/ScriptHostOptionsSetupTests.cs b/test/WebJobs.Script.Tests/Configuration/ScriptHostOptionsSetupTests.cs new file mode 100644 index 0000000000..8daa21b6a4 --- /dev/null +++ b/test/WebJobs.Script.Tests/Configuration/ScriptHostOptionsSetupTests.cs @@ -0,0 +1,92 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Azure.WebJobs.Script.WebHost; +using Microsoft.Azure.WebJobs.Script.WebHost.Configuration; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Options; +using Xunit; + +namespace Microsoft.Azure.WebJobs.Script.Tests.Configuration +{ + public class ScriptHostOptionsSetupTests + { + [Fact] + public void Configure_ApplicationInsightsConfig_NoSettings_CreatesDefaultSettings() + { + ScriptHostOptionsSetup setup = CreateSetupWithConfiguration(); + + var options = new ScriptHostOptions(); + setup.Configure(options); + + Assert.NotNull(options.ApplicationInsightsSamplingSettings); + Assert.Equal(5, options.ApplicationInsightsSamplingSettings.MaxTelemetryItemsPerSecond); + } + + [Fact] + public void Configure_FileWatching() + { + var settings = new Dictionary + { + { ConfigurationPath.Combine(ConfigurationSectionNames.JobHost, "fileWatchingEnabled"), "true" } + }; + + ScriptHostOptionsSetup setup = CreateSetupWithConfiguration(settings); + + var options = new ScriptHostOptions(); + + // Validate default (this should be in another test - migrated here for now) + Assert.True(options.FileWatchingEnabled); + + setup.Configure(options); + + Assert.True(options.FileWatchingEnabled); + Assert.Equal(1, options.WatchDirectories.Count); + Assert.Equal("node_modules", options.WatchDirectories.ElementAt(0)); + + // File watching disabled + settings[ConfigurationPath.Combine(ConfigurationSectionNames.JobHost, "fileWatchingEnabled")] = bool.FalseString; + + setup = CreateSetupWithConfiguration(settings); + + options = new ScriptHostOptions(); + setup.Configure(options); + + Assert.False(options.FileWatchingEnabled); + + // File watching enabled, watch directories + settings[ConfigurationPath.Combine(ConfigurationSectionNames.JobHost, "fileWatchingEnabled")] = bool.TrueString; + settings[ConfigurationPath.Combine(ConfigurationSectionNames.JobHost, "watchDirectories", "0")] = "Shared"; + settings[ConfigurationPath.Combine(ConfigurationSectionNames.JobHost, "watchDirectories", "1")] = "Tools"; + + setup = CreateSetupWithConfiguration(settings); + + options = new ScriptHostOptions(); + setup.Configure(options); + + Assert.True(options.FileWatchingEnabled); + Assert.Equal(3, options.WatchDirectories.Count); + Assert.Equal("node_modules", options.WatchDirectories.ElementAt(0)); + Assert.Equal("Shared", options.WatchDirectories.ElementAt(1)); + Assert.Equal("Tools", options.WatchDirectories.ElementAt(2)); + } + + private ScriptHostOptionsSetup CreateSetupWithConfiguration(Dictionary settings = null) + { + var builder = new ConfigurationBuilder(); + + if (settings != null) + { + builder.AddInMemoryCollection(settings); + } + + var configuration = builder.Build(); + + return new ScriptHostOptionsSetup(configuration, new OptionsWrapper(new ScriptWebHostOptions())); + } + } +} diff --git a/test/WebJobs.Script.Tests/Configuration/WebScriptHostConfigurationSourceTests.cs b/test/WebJobs.Script.Tests/Configuration/WebScriptHostConfigurationSourceTests.cs new file mode 100644 index 0000000000..f0d9e87e69 --- /dev/null +++ b/test/WebJobs.Script.Tests/Configuration/WebScriptHostConfigurationSourceTests.cs @@ -0,0 +1,13 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Microsoft.Azure.WebJobs.Script.Tests.Configuration +{ + public class WebScriptHostConfigurationSourceTests + { + } +} diff --git a/test/WebJobs.Script.Tests/FunctionMetadataManagerTests.cs b/test/WebJobs.Script.Tests/FunctionMetadataManagerTests.cs new file mode 100644 index 0000000000..befd689677 --- /dev/null +++ b/test/WebJobs.Script.Tests/FunctionMetadataManagerTests.cs @@ -0,0 +1,204 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.IO.Abstractions.TestingHelpers; +using System.Text; +using Newtonsoft.Json.Linq; +using Xunit; + +namespace Microsoft.Azure.WebJobs.Script.Tests +{ + public class FunctionMetadataManagerTests + { + [Theory] + [InlineData("QUEUETriggER.py")] + [InlineData("queueTrigger.py")] + public void DeterminePrimaryScriptFile_MultipleFiles_SourceFileSpecified(string scriptFileName) + { + JObject functionConfig = new JObject() + { + { "scriptFile", scriptFileName } + }; + + var files = new Dictionary + { + { @"c:\functions\queueTrigger.py", new MockFileData(string.Empty) }, + { @"c:\functions\helper.py", new MockFileData(string.Empty) }, + { @"c:\functions\test.txt", new MockFileData(string.Empty) } + }; + + var fileSystem = new MockFileSystem(files); + + string scriptFile = FunctionMetadataManager.DeterminePrimaryScriptFile(functionConfig, @"c:\functions", fileSystem); + Assert.Equal(@"c:\functions\queueTrigger.py", scriptFile, StringComparer.OrdinalIgnoreCase); + } + + [Fact] + public void DeterminePrimaryScriptFile_RelativeSourceFileSpecified() + { + JObject functionConfig = new JObject() + { + { "scriptFile", @"..\shared\queuetrigger.py" } + }; + + var files = new Dictionary + { + { @"c:\shared\queueTrigger.py", new MockFileData(string.Empty) }, + { @"c:\functions\queueTrigger.py", new MockFileData(string.Empty) }, + { @"c:\functions\helper.py", new MockFileData(string.Empty) }, + { @"c:\functions\test.txt", new MockFileData(string.Empty) } + }; + + var fileSystem = new MockFileSystem(files); + + string scriptFile = FunctionMetadataManager.DeterminePrimaryScriptFile(functionConfig, @"c:\functions", fileSystem); + Assert.Equal(@"c:\shared\queueTrigger.py", scriptFile, StringComparer.OrdinalIgnoreCase); + } + + [Fact] + public void DeterminePrimaryScriptFile_MultipleFiles_NoClearPrimary_ReturnsNull() + { + var functionConfig = new JObject(); + var files = new Dictionary + { + { @"c:\functions\foo.py", new MockFileData(string.Empty) }, + { @"c:\functions\queueTrigger.py", new MockFileData(string.Empty) }, + { @"c:\functions\helper.py", new MockFileData(string.Empty) }, + { @"c:\functions\test.txt", new MockFileData(string.Empty) } + }; + var fileSystem = new MockFileSystem(files); + Assert.Throws(() => FunctionMetadataManager.DeterminePrimaryScriptFile(functionConfig, @"c:\functions", fileSystem)); + } + + [Fact] + public void DeterminePrimaryScriptFile_NoFiles_ReturnsNull() + { + var functionConfig = new JObject(); + string[] functionFiles = new string[0]; + var fileSystem = new MockFileSystem(); + fileSystem.AddDirectory(@"c:\functions"); + + Assert.Throws(() => FunctionMetadataManager.DeterminePrimaryScriptFile(functionConfig, @"c:\functions", fileSystem)); + } + + [Fact] + public void DeterminePrimaryScriptFile_MultipleFiles_RunFilePresent() + { + var functionConfig = new JObject(); + var files = new Dictionary + { + { @"c:\functions\Run.csx", new MockFileData(string.Empty) }, + { @"c:\functions\Helper.csx", new MockFileData(string.Empty) }, + { @"c:\functions\test.txt", new MockFileData(string.Empty) } + }; + var fileSystem = new MockFileSystem(files); + + string scriptFile = FunctionMetadataManager.DeterminePrimaryScriptFile(functionConfig, @"c:\functions", fileSystem); + Assert.Equal(@"c:\functions\Run.csx", scriptFile); + } + + [Fact] + public void DeterminePrimaryScriptFile_SingleFile() + { + var functionConfig = new JObject(); + var files = new Dictionary + { + { @"c:\functions\Run.csx", new MockFileData(string.Empty) } + }; + var fileSystem = new MockFileSystem(files); + + string scriptFile = FunctionMetadataManager.DeterminePrimaryScriptFile(functionConfig, @"c:\functions", fileSystem); + Assert.Equal(@"c:\functions\Run.csx", scriptFile); + } + + [Fact] + public void DeterminePrimaryScriptFile_MultipleFiles_RunTrumpsIndex() + { + var functionConfig = new JObject(); + var files = new Dictionary + { + { @"c:\functions\run.js", new MockFileData(string.Empty) }, + { @"c:\functions\index.js", new MockFileData(string.Empty) }, + { @"c:\functions\test.txt", new MockFileData(string.Empty) } + }; + var fileSystem = new MockFileSystem(files); + + string scriptFile = FunctionMetadataManager.DeterminePrimaryScriptFile(functionConfig, @"c:\functions", fileSystem); + Assert.Equal(@"c:\functions\run.js", scriptFile); + } + + [Fact] + public void DeterminePrimaryScriptFile_MultipleFiles_IndexFilePresent() + { + var functionConfig = new JObject(); + var files = new Dictionary + { + { @"c:\functions\index.js", new MockFileData(string.Empty) }, + { @"c:\functions\test.txt", new MockFileData(string.Empty) } + }; + var fileSystem = new MockFileSystem(files); + + string scriptFile = FunctionMetadataManager.DeterminePrimaryScriptFile(functionConfig, @"c:\functions", fileSystem); + Assert.Equal(@"c:\functions\index.js", scriptFile); + } + + [Fact] + public void DeterminePrimaryScriptFile_MultipleFiles_ConfigTrumpsConvention() + { + JObject functionConfig = new JObject() + { + { "scriptFile", "queueTrigger.py" } + }; + var files = new Dictionary + { + { @"c:\functions\run.py", new MockFileData(string.Empty) }, + { @"c:\functions\queueTrigger.py", new MockFileData(string.Empty) }, + { @"c:\functions\helper.py", new MockFileData(string.Empty) }, + { @"c:\functions\test.txt", new MockFileData(string.Empty) } + }; + var fileSystem = new MockFileSystem(files); + + string scriptFile = FunctionMetadataManager.DeterminePrimaryScriptFile(functionConfig, @"c:\functions", fileSystem); + Assert.Equal(@"c:\functions\queueTrigger.py", scriptFile); + } + + [Theory] + [InlineData("")] + [InlineData("host")] + [InlineData("Host")] + [InlineData("-function")] + [InlineData("_function")] + [InlineData("function test")] + [InlineData("function.test")] + [InlineData("function0.1")] + public void ValidateFunctionName_ThrowsOnInvalidName(string functionName) + { + var ex = Assert.Throws(() => + { + FunctionMetadataManager.ValidateName(functionName); + }); + + Assert.Equal(string.Format("'{0}' is not a valid function name.", functionName), ex.Message); + } + + [Theory] + [InlineData("testwithhost")] + [InlineData("hosts")] + [InlineData("myfunction")] + [InlineData("myfunction-test")] + [InlineData("myfunction_test")] + public void ValidateFunctionName_DoesNotThrowOnValidName(string functionName) + { + try + { + FunctionMetadataManager.ValidateName(functionName); + } + catch (InvalidOperationException) + { + Assert.True(false, $"Valid function name {functionName} failed validation."); + } + } + } +} diff --git a/test/WebJobs.Script.Tests/ScriptHostTests.cs b/test/WebJobs.Script.Tests/ScriptHostTests.cs index 8430dfd72b..ad591180b8 100644 --- a/test/WebJobs.Script.Tests/ScriptHostTests.cs +++ b/test/WebJobs.Script.Tests/ScriptHostTests.cs @@ -273,170 +273,6 @@ public void GetAssemblyFileVersion_ReturnsVersion() asmMock.Verify(); } - [Theory] - [InlineData("QUEUETriggER.py")] - [InlineData("queueTrigger.py")] - public void DeterminePrimaryScriptFile_MultipleFiles_SourceFileSpecified(string scriptFileName) - { - JObject functionConfig = new JObject() - { - { "scriptFile", scriptFileName } - }; - - var files = new Dictionary - { - { @"c:\functions\queueTrigger.py", new MockFileData(string.Empty) }, - { @"c:\functions\helper.py", new MockFileData(string.Empty) }, - { @"c:\functions\test.txt", new MockFileData(string.Empty) } - }; - - var fileSystem = new MockFileSystem(files); - - // TODO: DI (FACAVAL) This logic has moved to FunctionMetadataManager - // string scriptFile = ScriptHost.DeterminePrimaryScriptFile(functionConfig, @"c:\functions", fileSystem); - // Assert.Equal(@"c:\functions\queueTrigger.py", scriptFile, StringComparer.OrdinalIgnoreCase); - throw new Exception("Fix test"); - } - - [Fact] - public void DeterminePrimaryScriptFile_RelativeSourceFileSpecified() - { - JObject functionConfig = new JObject() - { - { "scriptFile", @"..\shared\queuetrigger.py" } - }; - - var files = new Dictionary - { - { @"c:\shared\queueTrigger.py", new MockFileData(string.Empty) }, - { @"c:\functions\queueTrigger.py", new MockFileData(string.Empty) }, - { @"c:\functions\helper.py", new MockFileData(string.Empty) }, - { @"c:\functions\test.txt", new MockFileData(string.Empty) } - }; - - var fileSystem = new MockFileSystem(files); - - //string scriptFile = ScriptHost.DeterminePrimaryScriptFile(functionConfig, @"c:\functions", fileSystem); - //Assert.Equal(@"c:\shared\queueTrigger.py", scriptFile, StringComparer.OrdinalIgnoreCase); - throw new Exception("Fix test"); - } - - [Fact] - public void DeterminePrimaryScriptFile_MultipleFiles_ConfigTrumpsConvention() - { - JObject functionConfig = new JObject() - { - { "scriptFile", "queueTrigger.py" } - }; - var files = new Dictionary - { - { @"c:\functions\run.py", new MockFileData(string.Empty) }, - { @"c:\functions\queueTrigger.py", new MockFileData(string.Empty) }, - { @"c:\functions\helper.py", new MockFileData(string.Empty) }, - { @"c:\functions\test.txt", new MockFileData(string.Empty) } - }; - var fileSystem = new MockFileSystem(files); - - // TODO: DI (FACAVAL) This logic has moved to FunctionMetadataManager - //string scriptFile = ScriptHost.DeterminePrimaryScriptFile(functionConfig, @"c:\functions", fileSystem); - //Assert.Equal(@"c:\functions\queueTrigger.py", scriptFile); - throw new Exception("Fix test"); - } - - [Fact] - public void DeterminePrimaryScriptFile_MultipleFiles_NoClearPrimary_ReturnsNull() - { - var functionConfig = new JObject(); - var files = new Dictionary - { - { @"c:\functions\foo.py", new MockFileData(string.Empty) }, - { @"c:\functions\queueTrigger.py", new MockFileData(string.Empty) }, - { @"c:\functions\helper.py", new MockFileData(string.Empty) }, - { @"c:\functions\test.txt", new MockFileData(string.Empty) } - }; - var fileSystem = new MockFileSystem(files); - // TODO: DI (FACAVAL) This logic has moved to FunctionMetadataManager - //Assert.Throws(() => ScriptHost.DeterminePrimaryScriptFile(functionConfig, @"c:\functions", fileSystem)); - throw new Exception("Fix test"); - } - - [Fact] - public void DeterminePrimaryScriptFile_NoFiles_ReturnsNull() - { - var functionConfig = new JObject(); - string[] functionFiles = new string[0]; - var fileSystem = new MockFileSystem(); - fileSystem.AddDirectory(@"c:\functions"); - // TODO: DI (FACAVAL) This logic has moved to FunctionMetadataManager - // Assert.Throws(() => ScriptHost.DeterminePrimaryScriptFile(functionConfig, @"c:\functions", fileSystem)); - throw new Exception("Fix test"); - } - - [Fact] - public void DeterminePrimaryScriptFile_MultipleFiles_RunFilePresent() - { - var functionConfig = new JObject(); - var files = new Dictionary - { - { @"c:\functions\Run.csx", new MockFileData(string.Empty) }, - { @"c:\functions\Helper.csx", new MockFileData(string.Empty) }, - { @"c:\functions\test.txt", new MockFileData(string.Empty) } - }; - var fileSystem = new MockFileSystem(files); - // TODO: DI (FACAVAL) This logic has moved to FunctionMetadataManager - //string scriptFile = ScriptHost.DeterminePrimaryScriptFile(functionConfig, @"c:\functions", fileSystem); - //Assert.Equal(@"c:\functions\Run.csx", scriptFile); - throw new Exception("Fix test"); - } - - [Fact] - public void DeterminePrimaryScriptFile_SingleFile() - { - var functionConfig = new JObject(); - var files = new Dictionary - { - { @"c:\functions\Run.csx", new MockFileData(string.Empty) } - }; - var fileSystem = new MockFileSystem(files); - // TODO: DI (FACAVAL) This logic has moved to FunctionMetadataManager - //string scriptFile = ScriptHost.DeterminePrimaryScriptFile(functionConfig, @"c:\functions", fileSystem); - //Assert.Equal(@"c:\functions\Run.csx", scriptFile); - throw new Exception("Fix test"); - } - - [Fact] - public void DeterminePrimaryScriptFile_MultipleFiles_RunTrumpsIndex() - { - var functionConfig = new JObject(); - var files = new Dictionary - { - { @"c:\functions\run.js", new MockFileData(string.Empty) }, - { @"c:\functions\index.js", new MockFileData(string.Empty) }, - { @"c:\functions\test.txt", new MockFileData(string.Empty) } - }; - var fileSystem = new MockFileSystem(files); - // TODO: DI (FACAVAL) This logic has moved to FunctionMetadataManager - //string scriptFile = ScriptHost.DeterminePrimaryScriptFile(functionConfig, @"c:\functions", fileSystem); - //Assert.Equal(@"c:\functions\run.js", scriptFile); - throw new Exception("Fix test"); - } - - [Fact] - public void DeterminePrimaryScriptFile_MultipleFiles_IndexFilePresent() - { - var functionConfig = new JObject(); - var files = new Dictionary - { - { @"c:\functions\index.js", new MockFileData(string.Empty) }, - { @"c:\functions\test.txt", new MockFileData(string.Empty) } - }; - var fileSystem = new MockFileSystem(files); - // TODO: DI (FACAVAL) This logic has moved to FunctionMetadataManager - //string scriptFile = ScriptHost.DeterminePrimaryScriptFile(functionConfig, @"c:\functions", fileSystem); - //Assert.Equal(@"c:\functions\index.js", scriptFile); - throw new Exception("Fix test"); - } - [Fact(Skip = "Host.json parsing logic moved to HostJsonFileConfigurationSource. Move test")] public void Create_InvalidHostJson_ThrowsInformativeException() { @@ -651,7 +487,7 @@ public void ApplyConfiguration_Singleton() //Assert.Equal(8, scriptConfig.HostConfig.Singleton.LockAcquisitionPollingInterval.TotalSeconds); } - [Fact(Skip = "ApplyConfiguration no longer exists. Validate logic (moved to HostJsonFileConfigurationSource)")] + [Fact(Skip = "ApplyConfiguration no longer exists. Validate logic (moved to HostJsonFileConfigurationSource) - Also validate in setup test")] public void ApplyConfiguration_FileWatching() { //JObject config = new JObject(); @@ -1075,18 +911,6 @@ public void ApplyHostHealthMonitorConfig_AppliesExpectedSettings() //Assert.Equal(0.77F, scriptConfig.HostHealthMonitor.CounterThreshold); } - [Fact(Skip = "ApplyConfiguration no longer exists. Validate logic (moved to HostJsonFileConfigurationSource)")] - public void ApplyApplicationInsightsConfig_NoSettings_CreatesDefaultSettings() - { - //JObject config = JObject.Parse("{ }"); - - //ScriptHostConfiguration scriptConfig = new ScriptHostConfiguration(); - //ScriptHost.ApplyApplicationInsightsConfig(config, scriptConfig); - - //Assert.NotNull(scriptConfig.ApplicationInsightsSamplingSettings); - //Assert.Equal(5, scriptConfig.ApplicationInsightsSamplingSettings.MaxTelemetryItemsPerSecond); - } - [Fact(Skip = "ApplyConfiguration no longer exists. Validate logic (moved to HostJsonFileConfigurationSource)")] public void ApplyLoggerConfig_Sets_DefaultLevel() { @@ -1488,25 +1312,6 @@ public void TryGetFunctionFromException_FunctionMatch() Assert.Same(function, functionResult); } - [Theory(Skip = "Moved to FunctionMetadataManager")] - [InlineData("")] - [InlineData("host")] - [InlineData("Host")] - [InlineData("-function")] - [InlineData("_function")] - [InlineData("function test")] - [InlineData("function.test")] - [InlineData("function0.1")] - public void ValidateFunctionName_ThrowsOnInvalidName(string functionName) - { - var ex = Assert.Throws(() => - { - // ScriptHost.ValidateName(functionName); - }); - - Assert.Equal(string.Format("'{0}' is not a valid function name.", functionName), ex.Message); - } - [Theory] [InlineData("myproxy")] [InlineData("my proxy")] @@ -1516,24 +1321,6 @@ public void UpdateProxyName(string proxyName) Assert.Equal("myproxy", ScriptHost.NormalizeProxyName(proxyName)); } - [Theory(Skip = "Moved to FunctionMetadataManager")] - [InlineData("testwithhost")] - [InlineData("hosts")] - [InlineData("myfunction")] - [InlineData("myfunction-test")] - [InlineData("myfunction_test")] - public void ValidateFunctionName_DoesNotThrowOnValidName(string functionName) - { - try - { - //ScriptHost.ValidateName(functionName); - } - catch (InvalidOperationException) - { - Assert.True(false, $"Valid function name {functionName} failed validation."); - } - } - #if WEBROUTING [Fact] public void HttpRoutesConflict_ReturnsExpectedResult() @@ -1811,6 +1598,7 @@ public async Task InitializeAsync() .ConfigureDefaultTestScriptHost(o => { o.ScriptPath = TestHelpers.FunctionsTestDirectory; + o.LogPath = TestHelpers.GetHostLogFileDirectory().FullName; }) .Build();