From 307754a0e0a88ac331c1e8bb98e46ce51d004fd6 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Mon, 20 Apr 2020 15:39:55 -0400 Subject: Create a derived version of WebApplicationFactory<> that works with the Jellyfin server --- .../JellyfinApplicationFactory.cs | 124 +++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 tests/MediaBrowser.Api.Tests/JellyfinApplicationFactory.cs (limited to 'tests/MediaBrowser.Api.Tests/JellyfinApplicationFactory.cs') diff --git a/tests/MediaBrowser.Api.Tests/JellyfinApplicationFactory.cs b/tests/MediaBrowser.Api.Tests/JellyfinApplicationFactory.cs new file mode 100644 index 000000000..0bd9909f5 --- /dev/null +++ b/tests/MediaBrowser.Api.Tests/JellyfinApplicationFactory.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Emby.Server.Implementations; +using Emby.Server.Implementations.IO; +using Emby.Server.Implementations.Networking; +using Jellyfin.Drawing.Skia; +using Jellyfin.Server; +using MediaBrowser.Common; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Serilog; +using Serilog.Extensions.Logging; + +namespace MediaBrowser.Api.Tests +{ + /// + /// Factory for bootstrapping the Jellyfin application in memory for functional end to end tests. + /// + public class JellyfinApplicationFactory : WebApplicationFactory + { + private static readonly string _testPathRoot = Path.Combine(Path.GetTempPath(), "jellyfin-test-data"); + private static readonly ConcurrentBag _appHosts = new ConcurrentBag(); + + /// + /// Initializes a new instance of . + /// + public JellyfinApplicationFactory() + { + // Perform static initialization that only needs to happen once per test-run + Log.Logger = new LoggerConfiguration().WriteTo.Console().CreateLogger(); + Program.PerformStaticInitialization(); + } + + /// + protected override IWebHostBuilder CreateWebHostBuilder() + { + return new WebHostBuilder(); + } + + /// + protected override void ConfigureWebHost(IWebHostBuilder builder) + { + // Specify the startup command line options + var commandLineOpts = new StartupOptions + { + NoWebClient = true, + NoAutoRunWebApp = true + }; + + // Use a temporary directory for the application paths + var webHostPathRoot = Path.Combine(_testPathRoot, "test-host-" + Path.GetFileNameWithoutExtension(Path.GetRandomFileName())); + Directory.CreateDirectory(Path.Combine(webHostPathRoot, "logs")); + Directory.CreateDirectory(Path.Combine(webHostPathRoot, "config")); + Directory.CreateDirectory(Path.Combine(webHostPathRoot, "cache")); + Directory.CreateDirectory(Path.Combine(webHostPathRoot, "jellyfin-web")); + var appPaths = new ServerApplicationPaths( + webHostPathRoot, + Path.Combine(webHostPathRoot, "logs"), + Path.Combine(webHostPathRoot, "config"), + Path.Combine(webHostPathRoot, "cache"), + Path.Combine(webHostPathRoot, "jellyfin-web")); + + // Create the logging config file + // TODO: We shouldn't need to do this since we are only logging to console + Program.InitLoggingConfigFile(appPaths).Wait(); + + // Create a copy of the application configuration to use for startup + var startupConfig = Program.CreateAppConfiguration(commandLineOpts, appPaths); + + // Create the app host and initialize it + ILoggerFactory loggerFactory = new SerilogLoggerFactory(); + var appHost = new CoreAppHost( + appPaths, + loggerFactory, + commandLineOpts, + new ManagedFileSystem(loggerFactory.CreateLogger(), appPaths), + new SkiaEncoder(loggerFactory.CreateLogger(), appPaths), + new NetworkManager(loggerFactory.CreateLogger())); + _appHosts.Add(appHost); + var serviceCollection = new ServiceCollection(); + appHost.InitAsync(serviceCollection, startupConfig).Wait(); + + // Configure the web host builder + Program.ConfigureWebHostBuilder(builder, appHost, serviceCollection, commandLineOpts, startupConfig, appPaths); + } + + /// + protected override TestServer CreateServer(IWebHostBuilder builder) + { + // Create the test server using the base implementation + var testServer = base.CreateServer(builder); + + // Finish initializing the app host + var appHost = (CoreAppHost)testServer.Services.GetRequiredService(); + appHost.ServiceProvider = testServer.Services; + appHost.InitializeServices(); + appHost.FindParts(); + appHost.RunStartupTasksAsync().Wait(); + + return testServer; + } + + /// + protected override void Dispose(bool disposing) + { + foreach (var host in _appHosts) + { + host.Dispose(); + } + + _appHosts.Clear(); + + base.Dispose(disposing); + } + } +} -- cgit v1.2.3 From 6f20e2482f42d1224a8eb11d30d4eeff2e140c94 Mon Sep 17 00:00:00 2001 From: crobibero Date: Thu, 23 Apr 2020 12:43:05 -0600 Subject: Fix build --- tests/MediaBrowser.Api.Tests/BrandingServiceTests.cs | 3 --- tests/MediaBrowser.Api.Tests/JellyfinApplicationFactory.cs | 5 ----- tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj | 2 +- 3 files changed, 1 insertion(+), 9 deletions(-) (limited to 'tests/MediaBrowser.Api.Tests/JellyfinApplicationFactory.cs') diff --git a/tests/MediaBrowser.Api.Tests/BrandingServiceTests.cs b/tests/MediaBrowser.Api.Tests/BrandingServiceTests.cs index 881617914..34698fe25 100644 --- a/tests/MediaBrowser.Api.Tests/BrandingServiceTests.cs +++ b/tests/MediaBrowser.Api.Tests/BrandingServiceTests.cs @@ -1,9 +1,6 @@ -using System; using System.Text.Json; using System.Threading.Tasks; -using Jellyfin.Server; using MediaBrowser.Model.Branding; -using Microsoft.AspNetCore.Mvc.Testing; using Xunit; namespace MediaBrowser.Api.Tests diff --git a/tests/MediaBrowser.Api.Tests/JellyfinApplicationFactory.cs b/tests/MediaBrowser.Api.Tests/JellyfinApplicationFactory.cs index 0bd9909f5..4a01180bc 100644 --- a/tests/MediaBrowser.Api.Tests/JellyfinApplicationFactory.cs +++ b/tests/MediaBrowser.Api.Tests/JellyfinApplicationFactory.cs @@ -1,9 +1,5 @@ -using System; using System.Collections.Concurrent; -using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Threading.Tasks; using Emby.Server.Implementations; using Emby.Server.Implementations.IO; using Emby.Server.Implementations.Networking; @@ -14,7 +10,6 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Serilog; using Serilog.Extensions.Logging; diff --git a/tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj b/tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj index 077fefed0..b99d61f5a 100644 --- a/tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj +++ b/tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj @@ -1,4 +1,4 @@ - + netcoreapp3.1 -- cgit v1.2.3 From 7e467f9faa18168ddff0607751f3929e4e3e0285 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 25 Apr 2020 18:36:09 -0400 Subject: Use the correct method to synchronously wait for tasks to complete --- tests/MediaBrowser.Api.Tests/JellyfinApplicationFactory.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tests/MediaBrowser.Api.Tests/JellyfinApplicationFactory.cs') diff --git a/tests/MediaBrowser.Api.Tests/JellyfinApplicationFactory.cs b/tests/MediaBrowser.Api.Tests/JellyfinApplicationFactory.cs index 09821d728..5300d3661 100644 --- a/tests/MediaBrowser.Api.Tests/JellyfinApplicationFactory.cs +++ b/tests/MediaBrowser.Api.Tests/JellyfinApplicationFactory.cs @@ -65,7 +65,7 @@ namespace MediaBrowser.Api.Tests // Create the logging config file // TODO: We shouldn't need to do this since we are only logging to console - Program.InitLoggingConfigFile(appPaths).Wait(); + Program.InitLoggingConfigFile(appPaths).GetAwaiter().GetResult(); // Create a copy of the application configuration to use for startup var startupConfig = Program.CreateAppConfiguration(commandLineOpts, appPaths); @@ -95,8 +95,8 @@ namespace MediaBrowser.Api.Tests // Finish initializing the app host var appHost = (CoreAppHost)testServer.Services.GetRequiredService(); appHost.ServiceProvider = testServer.Services; - appHost.InitializeServices().Wait(); - appHost.RunStartupTasksAsync().Wait(); + appHost.InitializeServices().GetAwaiter().GetResult(); + appHost.RunStartupTasksAsync().GetAwaiter().GetResult(); return testServer; } -- cgit v1.2.3 From ea82e2158c6ffda98d59d711cad36ff74ef14af8 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sun, 3 May 2020 15:31:17 -0400 Subject: Make sure logger factories are disposed during integration tests --- .../MediaBrowser.Api.Tests/JellyfinApplicationFactory.cs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'tests/MediaBrowser.Api.Tests/JellyfinApplicationFactory.cs') diff --git a/tests/MediaBrowser.Api.Tests/JellyfinApplicationFactory.cs b/tests/MediaBrowser.Api.Tests/JellyfinApplicationFactory.cs index 5300d3661..558539761 100644 --- a/tests/MediaBrowser.Api.Tests/JellyfinApplicationFactory.cs +++ b/tests/MediaBrowser.Api.Tests/JellyfinApplicationFactory.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Concurrent; using System.IO; using Emby.Server.Implementations; @@ -22,7 +23,7 @@ namespace MediaBrowser.Api.Tests public class JellyfinApplicationFactory : WebApplicationFactory { private static readonly string _testPathRoot = Path.Combine(Path.GetTempPath(), "jellyfin-test-data"); - private static readonly ConcurrentBag _appHosts = new ConcurrentBag(); + private static readonly ConcurrentBag _disposableComponents = new ConcurrentBag(); /// /// Initializes a new instance of . @@ -70,15 +71,17 @@ namespace MediaBrowser.Api.Tests // Create a copy of the application configuration to use for startup var startupConfig = Program.CreateAppConfiguration(commandLineOpts, appPaths); - // Create the app host and initialize it ILoggerFactory loggerFactory = new SerilogLoggerFactory(); + _disposableComponents.Add(loggerFactory); + + // Create the app host and initialize it var appHost = new CoreAppHost( appPaths, loggerFactory, commandLineOpts, new ManagedFileSystem(loggerFactory.CreateLogger(), appPaths), new NetworkManager(loggerFactory.CreateLogger())); - _appHosts.Add(appHost); + _disposableComponents.Add(appHost); var serviceCollection = new ServiceCollection(); appHost.Init(serviceCollection); @@ -104,12 +107,12 @@ namespace MediaBrowser.Api.Tests /// protected override void Dispose(bool disposing) { - foreach (var host in _appHosts) + foreach (var disposable in _disposableComponents) { - host.Dispose(); + disposable.Dispose(); } - _appHosts.Clear(); + _disposableComponents.Clear(); base.Dispose(disposing); } -- cgit v1.2.3 From e66b0001830c36e83a4f2fda125264d9b9527243 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sun, 3 May 2020 16:23:42 -0400 Subject: Enable StyleCop and FxCop analyzers for integration tests project Use a custom ruleset that derives from the base solution ruleset, overriding rules where necessary --- .../JellyfinApplicationFactory.cs | 2 +- .../MediaBrowser.Api.Tests.csproj | 10 ++++++++++ .../MediaBrowser.Api.Tests.ruleset | 22 ++++++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.ruleset (limited to 'tests/MediaBrowser.Api.Tests/JellyfinApplicationFactory.cs') diff --git a/tests/MediaBrowser.Api.Tests/JellyfinApplicationFactory.cs b/tests/MediaBrowser.Api.Tests/JellyfinApplicationFactory.cs index 558539761..c39ed07de 100644 --- a/tests/MediaBrowser.Api.Tests/JellyfinApplicationFactory.cs +++ b/tests/MediaBrowser.Api.Tests/JellyfinApplicationFactory.cs @@ -26,7 +26,7 @@ namespace MediaBrowser.Api.Tests private static readonly ConcurrentBag _disposableComponents = new ConcurrentBag(); /// - /// Initializes a new instance of . + /// Initializes a new instance of the class. /// public JellyfinApplicationFactory() { diff --git a/tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj b/tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj index b99d61f5a..8ae110c32 100644 --- a/tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj +++ b/tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj @@ -20,4 +20,14 @@ + + + + + + + + MediaBrowser.Api.Tests.ruleset + + diff --git a/tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.ruleset b/tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.ruleset new file mode 100644 index 000000000..5cf77ac4c --- /dev/null +++ b/tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.ruleset @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3