diff --git a/src/libraries/Microsoft.Extensions.Hosting.Abstractions/tests/EnvironmentsTests.cs b/src/libraries/Microsoft.Extensions.Hosting.Abstractions/tests/EnvironmentsTests.cs new file mode 100644 index 00000000000000..6a89b485c64bae --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Hosting.Abstractions/tests/EnvironmentsTests.cs @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Xunit; + +namespace Microsoft.Extensions.Hosting.Tests +{ + public class EnvironmentsTests + { + [Fact] + public void EnvironmentConstants_HaveExpectedValues() + { + Assert.Equal("Development", Environments.Development); + Assert.Equal("Staging", Environments.Staging); + Assert.Equal("Production", Environments.Production); + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Hosting.Abstractions/tests/HostBuilderContextTests.cs b/src/libraries/Microsoft.Extensions.Hosting.Abstractions/tests/HostBuilderContextTests.cs new file mode 100644 index 00000000000000..44903b3aca6760 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Hosting.Abstractions/tests/HostBuilderContextTests.cs @@ -0,0 +1,105 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.FileProviders; +using Xunit; + +namespace Microsoft.Extensions.Hosting.Tests +{ + using AssertExtensions = System.AssertExtensions; + + public class HostBuilderContextTests + { + [Fact] + public void Constructor_WithProperties_InitializesProperties() + { + var properties = new Dictionary(); + var context = new HostBuilderContext(properties); + + Assert.Same(properties, context.Properties); + } + + [Fact] + public void Constructor_WithNullProperties_ThrowsArgumentNullException() + { + AssertExtensions.Throws("properties", () => new HostBuilderContext(null)); + } + + [Fact] + public void HostingEnvironment_CanBeSet() + { + var properties = new Dictionary(); + var context = new HostBuilderContext(properties); + var environment = new TestHostEnvironment(); + + context.HostingEnvironment = environment; + + Assert.Same(environment, context.HostingEnvironment); + } + + [Fact] + public void Configuration_CanBeSet() + { + var properties = new Dictionary(); + var context = new HostBuilderContext(properties); + var configuration = new ConfigurationBuilder().Build(); + + context.Configuration = configuration; + + Assert.Same(configuration, context.Configuration); + } + + [Fact] + public void Properties_CanBeModified() + { + var properties = new Dictionary(); + var context = new HostBuilderContext(properties); + + context.Properties["key1"] = "value1"; + context.Properties["key2"] = 42; + + Assert.Equal("value1", context.Properties["key1"]); + Assert.Equal(42, context.Properties["key2"]); + } + + [Fact] + public void Properties_SharedWithConstructorDictionary() + { + var properties = new Dictionary + { + ["existing"] = "value" + }; + var context = new HostBuilderContext(properties); + + properties["new"] = "added"; + + Assert.Equal("added", context.Properties["new"]); + } + + [Fact] + public void AllProperties_CanBeSetTogether() + { + var properties = new Dictionary(); + var context = new HostBuilderContext(properties) + { + HostingEnvironment = new TestHostEnvironment(), + Configuration = new ConfigurationBuilder().Build() + }; + + Assert.NotNull(context.HostingEnvironment); + Assert.NotNull(context.Configuration); + Assert.Same(properties, context.Properties); + } + + private class TestHostEnvironment : IHostEnvironment + { + public string EnvironmentName { get; set; } = string.Empty; + public string ApplicationName { get; set; } = string.Empty; + public string ContentRootPath { get; set; } = string.Empty; + public IFileProvider ContentRootFileProvider { get; set; } = null!; + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Hosting.Abstractions/tests/HostDefaultsTests.cs b/src/libraries/Microsoft.Extensions.Hosting.Abstractions/tests/HostDefaultsTests.cs new file mode 100644 index 00000000000000..589cb00c4ce7ab --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Hosting.Abstractions/tests/HostDefaultsTests.cs @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Xunit; + +namespace Microsoft.Extensions.Hosting.Tests +{ + public class HostDefaultsTests + { + [Fact] + public void KeyConstants_HaveExpectedValues() + { + Assert.Equal("applicationName", HostDefaults.ApplicationKey); + Assert.Equal("environment", HostDefaults.EnvironmentKey); + Assert.Equal("contentRoot", HostDefaults.ContentRootKey); + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Hosting.Abstractions/tests/HostEnvironmentEnvExtensionsTests.cs b/src/libraries/Microsoft.Extensions.Hosting.Abstractions/tests/HostEnvironmentEnvExtensionsTests.cs new file mode 100644 index 00000000000000..67219370e9c219 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Hosting.Abstractions/tests/HostEnvironmentEnvExtensionsTests.cs @@ -0,0 +1,144 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using Microsoft.Extensions.FileProviders; +using Xunit; + +namespace Microsoft.Extensions.Hosting.Tests +{ + public class HostEnvironmentEnvExtensionsTests + { + [Fact] + public void IsDevelopment_WithDevelopmentEnvironment_ReturnsTrue() + { + var environment = new TestHostEnvironment { EnvironmentName = Environments.Development }; + + Assert.True(environment.IsDevelopment()); + } + + [Fact] + public void IsDevelopment_WithNonDevelopmentEnvironment_ReturnsFalse() + { + var environment = new TestHostEnvironment { EnvironmentName = Environments.Production }; + + Assert.False(environment.IsDevelopment()); + } + + [Fact] + public void IsDevelopment_WithNullEnvironment_ThrowsArgumentNullException() + { + IHostEnvironment environment = null; + + Assert.Throws(() => environment.IsDevelopment()); + } + + [Fact] + public void IsStaging_WithStagingEnvironment_ReturnsTrue() + { + var environment = new TestHostEnvironment { EnvironmentName = Environments.Staging }; + + Assert.True(environment.IsStaging()); + } + + [Fact] + public void IsStaging_WithNonStagingEnvironment_ReturnsFalse() + { + var environment = new TestHostEnvironment { EnvironmentName = Environments.Production }; + + Assert.False(environment.IsStaging()); + } + + [Fact] + public void IsStaging_WithNullEnvironment_ThrowsArgumentNullException() + { + IHostEnvironment environment = null; + + Assert.Throws(() => environment.IsStaging()); + } + + [Fact] + public void IsProduction_WithProductionEnvironment_ReturnsTrue() + { + var environment = new TestHostEnvironment { EnvironmentName = Environments.Production }; + + Assert.True(environment.IsProduction()); + } + + [Fact] + public void IsProduction_WithNonProductionEnvironment_ReturnsFalse() + { + var environment = new TestHostEnvironment { EnvironmentName = Environments.Development }; + + Assert.False(environment.IsProduction()); + } + + [Fact] + public void IsProduction_WithNullEnvironment_ThrowsArgumentNullException() + { + IHostEnvironment environment = null; + + Assert.Throws(() => environment.IsProduction()); + } + + [Theory] + [InlineData("Development", "Development", true)] + [InlineData("Development", "development", true)] + [InlineData("Development", "DEVELOPMENT", true)] + [InlineData("Development", "Production", false)] + [InlineData("Production", "Production", true)] + [InlineData("Staging", "staging", true)] + [InlineData("Custom", "Custom", true)] + [InlineData("Custom", "custom", true)] + public void IsEnvironment_ComparesEnvironmentNameCaseInsensitive(string actualEnvironment, string testEnvironment, bool expected) + { + var environment = new TestHostEnvironment { EnvironmentName = actualEnvironment }; + + Assert.Equal(expected, environment.IsEnvironment(testEnvironment)); + } + + [Fact] + public void IsEnvironment_WithNullEnvironment_ThrowsArgumentNullException() + { + IHostEnvironment environment = null; + + Assert.Throws(() => environment.IsEnvironment("Development")); + } + + [Fact] + public void IsEnvironment_WithEmptyString_ReturnsFalseForNonEmptyEnvironmentName() + { + var environment = new TestHostEnvironment { EnvironmentName = "Development" }; + + Assert.False(environment.IsEnvironment(string.Empty)); + } + + [Fact] + public void IsEnvironment_WithEmptyEnvironmentName_ReturnsTrueForEmptyString() + { + var environment = new TestHostEnvironment { EnvironmentName = string.Empty }; + + Assert.True(environment.IsEnvironment(string.Empty)); + } + + [Fact] + public void EnvironmentChecks_AreCaseInsensitive() + { + var devEnv = new TestHostEnvironment { EnvironmentName = "development" }; + var stagingEnv = new TestHostEnvironment { EnvironmentName = "STAGING" }; + var prodEnv = new TestHostEnvironment { EnvironmentName = "PrOdUcTiOn" }; + + Assert.True(devEnv.IsDevelopment()); + Assert.True(stagingEnv.IsStaging()); + Assert.True(prodEnv.IsProduction()); + } + + private class TestHostEnvironment : IHostEnvironment + { + public string EnvironmentName { get; set; } = string.Empty; + public string ApplicationName { get; set; } = string.Empty; + public string ContentRootPath { get; set; } = string.Empty; + public IFileProvider ContentRootFileProvider { get; set; } = null!; + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Hosting.Abstractions/tests/Microsoft.Extensions.Hosting.Abstractions.Tests.csproj b/src/libraries/Microsoft.Extensions.Hosting.Abstractions/tests/Microsoft.Extensions.Hosting.Abstractions.Tests.csproj new file mode 100644 index 00000000000000..886164bfcc8c4c --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Hosting.Abstractions/tests/Microsoft.Extensions.Hosting.Abstractions.Tests.csproj @@ -0,0 +1,13 @@ + + + + $(NetCoreAppCurrent);$(NetFrameworkCurrent) + true + + + + + + + + diff --git a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/BackgroundServiceExceptionBehaviorTests.cs b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/BackgroundServiceExceptionBehaviorTests.cs new file mode 100644 index 00000000000000..e925cbb343464c --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/BackgroundServiceExceptionBehaviorTests.cs @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Xunit; + +namespace Microsoft.Extensions.Hosting.Tests +{ + public class BackgroundServiceExceptionBehaviorTests + { + [Fact] + public void EnumValues_HaveExpectedValues() + { + Assert.Equal(0, (int)BackgroundServiceExceptionBehavior.StopHost); + Assert.Equal(1, (int)BackgroundServiceExceptionBehavior.Ignore); + } + + [Fact] + public void CanCompareValues() + { + var stopHost = BackgroundServiceExceptionBehavior.StopHost; + var ignore = BackgroundServiceExceptionBehavior.Ignore; + + Assert.True(stopHost == BackgroundServiceExceptionBehavior.StopHost); + Assert.True(ignore == BackgroundServiceExceptionBehavior.Ignore); + Assert.False(stopHost == ignore); + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/ConsoleLifetimeOptionsTests.cs b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/ConsoleLifetimeOptionsTests.cs new file mode 100644 index 00000000000000..bce3168e3b7987 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/ConsoleLifetimeOptionsTests.cs @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Xunit; + +namespace Microsoft.Extensions.Hosting.Tests +{ + public class ConsoleLifetimeOptionsTests + { + [Fact] + public void SuppressStatusMessages_CanBeToggled() + { + var options = new ConsoleLifetimeOptions(); + Assert.False(options.SuppressStatusMessages); + + options.SuppressStatusMessages = true; + Assert.True(options.SuppressStatusMessages); + + options.SuppressStatusMessages = false; + Assert.False(options.SuppressStatusMessages); + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/HostApplicationBuilderSettingsTests.cs b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/HostApplicationBuilderSettingsTests.cs new file mode 100644 index 00000000000000..aff298093a3206 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/HostApplicationBuilderSettingsTests.cs @@ -0,0 +1,81 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Extensions.Configuration; +using Xunit; + +namespace Microsoft.Extensions.Hosting.Tests +{ + public class HostApplicationBuilderSettingsTests + { + [Fact] + public void Constructor_InitializesWithDefaults() + { + var settings = new HostApplicationBuilderSettings(); + + Assert.False(settings.DisableDefaults); + Assert.Null(settings.Args); + Assert.Null(settings.Configuration); + Assert.Null(settings.EnvironmentName); + Assert.Null(settings.ApplicationName); + Assert.Null(settings.ContentRootPath); + } + + [Fact] + public void AllProperties_CanBeSetTogether() + { + var args = new[] { "--key", "value" }; + var configuration = new ConfigurationManager(); + var settings = new HostApplicationBuilderSettings + { + DisableDefaults = true, + Args = args, + Configuration = configuration, + EnvironmentName = "Development", + ApplicationName = "TestApp", + ContentRootPath = "/test" + }; + + Assert.True(settings.DisableDefaults); + Assert.Same(args, settings.Args); + Assert.Same(configuration, settings.Configuration); + Assert.Equal("Development", settings.EnvironmentName); + Assert.Equal("TestApp", settings.ApplicationName); + Assert.Equal("/test", settings.ContentRootPath); + } + + [Fact] + public void EmptyArgs_CanBeSet() + { + var settings = new HostApplicationBuilderSettings + { + Args = new string[0] + }; + + Assert.NotNull(settings.Args); + Assert.Empty(settings.Args); + } + + [Fact] + public void Properties_CanBeCleared() + { + var settings = new HostApplicationBuilderSettings + { + Args = new[] { "test" }, + EnvironmentName = "Test", + ApplicationName = "App", + ContentRootPath = "/path" + }; + + settings.Args = null; + settings.EnvironmentName = null; + settings.ApplicationName = null; + settings.ContentRootPath = null; + + Assert.Null(settings.Args); + Assert.Null(settings.EnvironmentName); + Assert.Null(settings.ApplicationName); + Assert.Null(settings.ContentRootPath); + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/HostOptionsTests.cs b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/HostOptionsTests.cs new file mode 100644 index 00000000000000..7a091383f78c71 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/HostOptionsTests.cs @@ -0,0 +1,94 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Threading; +using Xunit; + +namespace Microsoft.Extensions.Hosting.Tests +{ + public class HostOptionsTests + { + [Fact] + public void DefaultValues_AreSet() + { + var options = new HostOptions(); + + Assert.Equal(TimeSpan.FromSeconds(30), options.ShutdownTimeout); + Assert.Equal(Timeout.InfiniteTimeSpan, options.StartupTimeout); + Assert.False(options.ServicesStartConcurrently); + Assert.False(options.ServicesStopConcurrently); + Assert.Equal(BackgroundServiceExceptionBehavior.StopHost, options.BackgroundServiceExceptionBehavior); + } + + [Fact] + public void Properties_CanBeSetDirectly() + { + var options = new HostOptions + { + ShutdownTimeout = TimeSpan.FromSeconds(60), + StartupTimeout = TimeSpan.FromSeconds(90), + ServicesStartConcurrently = true, + ServicesStopConcurrently = true, + BackgroundServiceExceptionBehavior = BackgroundServiceExceptionBehavior.Ignore + }; + + Assert.Equal(TimeSpan.FromSeconds(60), options.ShutdownTimeout); + Assert.Equal(TimeSpan.FromSeconds(90), options.StartupTimeout); + Assert.True(options.ServicesStartConcurrently); + Assert.True(options.ServicesStopConcurrently); + Assert.Equal(BackgroundServiceExceptionBehavior.Ignore, options.BackgroundServiceExceptionBehavior); + } + + [Fact] + public void Properties_CanBeUpdated() + { + var options = new HostOptions + { + ShutdownTimeout = TimeSpan.FromSeconds(10), + StartupTimeout = TimeSpan.FromSeconds(20) + }; + + options.ShutdownTimeout = TimeSpan.FromSeconds(50); + options.StartupTimeout = TimeSpan.FromSeconds(100); + + Assert.Equal(TimeSpan.FromSeconds(50), options.ShutdownTimeout); + Assert.Equal(TimeSpan.FromSeconds(100), options.StartupTimeout); + } + + [Fact] + public void ShutdownTimeout_AcceptsZero() + { + var options = new HostOptions + { + ShutdownTimeout = TimeSpan.Zero + }; + + Assert.Equal(TimeSpan.Zero, options.ShutdownTimeout); + } + + [Fact] + public void StartupTimeout_AcceptsZero() + { + var options = new HostOptions + { + StartupTimeout = TimeSpan.Zero + }; + + Assert.Equal(TimeSpan.Zero, options.StartupTimeout); + } + + [Fact] + public void Timeouts_AcceptMaxValue() + { + var options = new HostOptions + { + ShutdownTimeout = TimeSpan.MaxValue, + StartupTimeout = TimeSpan.MaxValue + }; + + Assert.Equal(TimeSpan.MaxValue, options.ShutdownTimeout); + Assert.Equal(TimeSpan.MaxValue, options.StartupTimeout); + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/Internal/HostingEnvironmentTests.cs b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/Internal/HostingEnvironmentTests.cs new file mode 100644 index 00000000000000..d3fc77e26bd406 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/Internal/HostingEnvironmentTests.cs @@ -0,0 +1,71 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Extensions.FileProviders; +using Xunit; + +namespace Microsoft.Extensions.Hosting.Internal.Tests +{ + public class HostingEnvironmentTests + { + [Fact] + public void DefaultValues_AreEmptyStrings() + { + var environment = new HostingEnvironment(); + + Assert.Equal(string.Empty, environment.EnvironmentName); + Assert.Equal(string.Empty, environment.ApplicationName); + Assert.Equal(string.Empty, environment.ContentRootPath); + } + + [Fact] + public void AllProperties_CanBeSetTogether() + { + var fileProvider = new PhysicalFileProvider("/"); + var environment = new HostingEnvironment + { + EnvironmentName = "Production", + ApplicationName = "TestApplication", + ContentRootPath = "/test/path", + ContentRootFileProvider = fileProvider + }; + + Assert.Equal("Production", environment.EnvironmentName); + Assert.Equal("TestApplication", environment.ApplicationName); + Assert.Equal("/test/path", environment.ContentRootPath); + Assert.Same(fileProvider, environment.ContentRootFileProvider); + } + + [Fact] + public void ImplementsIHostEnvironment() + { + var environment = new HostingEnvironment(); + Assert.IsAssignableFrom(environment); + } + + [Fact] + public void ImplementsIHostingEnvironment() + { + var environment = new HostingEnvironment(); +#pragma warning disable CS0618 // Type or member is obsolete + Assert.IsAssignableFrom(environment); +#pragma warning restore CS0618 // Type or member is obsolete + } + + [Fact] + public void Properties_CanBeUpdated() + { + var environment = new HostingEnvironment + { + EnvironmentName = "Development", + ApplicationName = "App1" + }; + + environment.EnvironmentName = "Staging"; + environment.ApplicationName = "App2"; + + Assert.Equal("Staging", environment.EnvironmentName); + Assert.Equal("App2", environment.ApplicationName); + } + } +}