diff options
25 files changed, 161 insertions, 91 deletions
diff --git a/.ci/azure-pipelines-test.yml b/.ci/azure-pipelines-test.yml index 95e0d8c58..7838b3b02 100644 --- a/.ci/azure-pipelines-test.yml +++ b/.ci/azure-pipelines-test.yml @@ -94,5 +94,5 @@ jobs: displayName: 'Publish OpenAPI Artifact' condition: and(succeeded(), eq(variables['Agent.OS'], 'Linux')) inputs: - targetPath: "tests/Jellyfin.Api.Tests/bin/Release/net5.0/openapi.json" + targetPath: "tests/Jellyfin.Server.Integration.Tests/bin/Release/net5.0/openapi.json" artifactName: 'OpenAPI Spec' diff --git a/Emby.Dlna/Profiles/DefaultProfile.cs b/Emby.Dlna/Profiles/DefaultProfile.cs index d4af72b62..8eaf12ba9 100644 --- a/Emby.Dlna/Profiles/DefaultProfile.cs +++ b/Emby.Dlna/Profiles/DefaultProfile.cs @@ -1,5 +1,7 @@ #pragma warning disable CS1591 +using System; +using System.Globalization; using System.Linq; using MediaBrowser.Model.Dlna; @@ -10,6 +12,7 @@ namespace Emby.Dlna.Profiles { public DefaultProfile() { + Id = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture); Name = "Generic Device"; ProtocolInfo = "http-get:*:video/mpeg:*,http-get:*:video/mp4:*,http-get:*:video/vnd.dlna.mpeg-tts:*,http-get:*:video/avi:*,http-get:*:video/x-matroska:*,http-get:*:video/x-ms-wmv:*,http-get:*:video/wtv:*,http-get:*:audio/mpeg:*,http-get:*:audio/mp3:*,http-get:*:audio/mp4:*,http-get:*:audio/x-ms-wma:*,http-get:*:audio/wav:*,http-get:*:audio/L16:*,http-get:*:image/jpeg:*,http-get:*:image/png:*,http-get:*:image/gif:*,http-get:*:image/tiff:*"; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 40b934d32..78a82118e 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -91,8 +91,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV Directory.CreateDirectory(Path.GetDirectoryName(logFilePath)); // FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory. - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - _logFileStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, true); + _logFileStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true); await JsonSerializer.SerializeAsync(_logFileStream, mediaSource, _jsonOptions, cancellationToken).ConfigureAwait(false); await _logFileStream.WriteAsync(Encoding.UTF8.GetBytes(Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine), cancellationToken).ConfigureAwait(false); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs index 08832bae1..b16ccc561 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs @@ -193,8 +193,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { var resolved = false; - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None)) + using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read)) { while (true) { diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs index 233c3d83a..eeb2426f4 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs @@ -136,8 +136,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts Logger.LogInformation("Beginning {0} stream to {1}", GetType().Name, TempFilePath); using var message = response; await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - await using var fileStream = new FileStream(TempFilePath, FileMode.Create, FileAccess.Write, FileShare.None); + await using var fileStream = new FileStream(TempFilePath, FileMode.Create, FileAccess.Write, FileShare.Read); await StreamHelper.CopyToAsync( stream, fileStream, diff --git a/Jellyfin.Api/Helpers/StreamingHelpers.cs b/Jellyfin.Api/Helpers/StreamingHelpers.cs index d20a02cf5..e2306aa27 100644 --- a/Jellyfin.Api/Helpers/StreamingHelpers.cs +++ b/Jellyfin.Api/Helpers/StreamingHelpers.cs @@ -508,17 +508,15 @@ namespace Jellyfin.Api.Helpers private static void ApplyDeviceProfileSettings(StreamState state, IDlnaManager dlnaManager, IDeviceManager deviceManager, HttpRequest request, string? deviceProfileId, bool? @static) { - var headers = request.Headers; - if (!string.IsNullOrWhiteSpace(deviceProfileId)) { state.DeviceProfile = dlnaManager.GetProfile(deviceProfileId); - } - else if (!string.IsNullOrWhiteSpace(deviceProfileId)) - { - var caps = deviceManager.GetCapabilities(deviceProfileId); - state.DeviceProfile = caps == null ? dlnaManager.GetProfile(headers) : caps.DeviceProfile; + if (state.DeviceProfile == null) + { + var caps = deviceManager.GetCapabilities(deviceProfileId); + state.DeviceProfile = caps == null ? dlnaManager.GetProfile(request.Headers) : caps.DeviceProfile; + } } var profile = state.DeviceProfile; diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index 7cd9024b0..240d132b1 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs @@ -553,8 +553,7 @@ namespace Jellyfin.Api.Helpers $"{logFilePrefix}{DateTime.Now:yyyy-MM-dd_HH-mm-ss}_{state.Request.MediaSourceId}_{Guid.NewGuid().ToString()[..8]}.log"); // FFmpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory. - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - Stream logStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, true); + Stream logStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true); var commandLineLogMessageBytes = Encoding.UTF8.GetBytes(request.Path + Environment.NewLine + Environment.NewLine + JsonSerializer.Serialize(state.MediaSource) + Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine); await logStream.WriteAsync(commandLineLogMessageBytes, 0, commandLineLogMessageBytes.Length, cancellationTokenSource.Token).ConfigureAwait(false); diff --git a/Jellyfin.Server/Properties/AssemblyInfo.cs b/Jellyfin.Server/Properties/AssemblyInfo.cs index 7abf298b1..fe2d5c5f9 100644 --- a/Jellyfin.Server/Properties/AssemblyInfo.cs +++ b/Jellyfin.Server/Properties/AssemblyInfo.cs @@ -21,4 +21,4 @@ using System.Runtime.InteropServices; // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] -[assembly: InternalsVisibleTo("Jellyfin.Api.Tests")] +[assembly: InternalsVisibleTo("Jellyfin.Server.Tests")] diff --git a/Jellyfin.sln b/Jellyfin.sln index 02ac1c7e9..7b81f4346 100644 --- a/Jellyfin.sln +++ b/Jellyfin.sln @@ -76,6 +76,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.Model.Tests", "tes EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.Networking.Tests", "tests\Jellyfin.Networking.Tests\Jellyfin.Networking.Tests.csproj", "{42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.Server.Integration.Tests", "tests\Jellyfin.Server.Integration.Tests\Jellyfin.Server.Integration.Tests.csproj", "{25E40B0B-7C89-4230-8911-CBBBCE83FC5B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.Server.Tests", "tests\Jellyfin.Server.Tests\Jellyfin.Server.Tests.csproj", "{3ADBCD8C-C0F2-4956-8FDC-35D686B74CF9}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -206,6 +210,10 @@ Global {42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}.Debug|Any CPU.Build.0 = Debug|Any CPU {42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}.Release|Any CPU.ActiveCfg = Release|Any CPU {42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}.Release|Any CPU.Build.0 = Release|Any CPU + {3ADBCD8C-C0F2-4956-8FDC-35D686B74CF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3ADBCD8C-C0F2-4956-8FDC-35D686B74CF9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3ADBCD8C-C0F2-4956-8FDC-35D686B74CF9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3ADBCD8C-C0F2-4956-8FDC-35D686B74CF9}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -221,6 +229,7 @@ Global {30922383-D513-4F4D-B890-A940B57FA353} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6} {FC1BC0CE-E8D2-4AE9-A6AB-8A02143B335D} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6} {42816EA8-4511-4CBF-A9C7-7791D5DDDAE6} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6} + {3ADBCD8C-C0F2-4956-8FDC-35D686B74CF9} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {3448830C-EBDC-426C-85CD-7BBB9651A7FE} diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs index 9a3e3d5fa..2cd1ee717 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs @@ -140,7 +140,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies // ParseName is required here. // Caller provides the filename with extension stripped and NOT the parsed filename var parsedName = _libraryManager.ParseName(info.Name); - var searchResults = await _tmdbClientManager.SearchMovieAsync(parsedName.Name, parsedName.Year ?? 0, info.MetadataLanguage, cancellationToken).ConfigureAwait(false); + var searchResults = await _tmdbClientManager.SearchMovieAsync(parsedName.Name, info.Year ?? parsedName.Year ?? 0, info.MetadataLanguage, cancellationToken).ConfigureAwait(false); if (searchResults.Count > 0) { @@ -148,6 +148,15 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies } } + if (string.IsNullOrEmpty(tmdbId) && !string.IsNullOrEmpty(imdbId)) + { + var movieResultFromImdbId = await _tmdbClientManager.FindByExternalIdAsync(imdbId, FindExternalSource.Imdb, info.MetadataLanguage, cancellationToken).ConfigureAwait(false); + if (movieResultFromImdbId?.MovieResults.Count > 0) + { + tmdbId = movieResultFromImdbId.MovieResults[0].Id.ToString(); + } + } + if (string.IsNullOrEmpty(tmdbId)) { return new MetadataResult<Movie>(); diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs index 0238d0574..74c2acf47 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs @@ -43,9 +43,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(SeriesInfo searchInfo, CancellationToken cancellationToken) { - var tmdbId = searchInfo.GetProviderId(MetadataProvider.Tmdb); - - if (!string.IsNullOrEmpty(tmdbId)) + if (searchInfo.TryGetProviderId(MetadataProvider.Tmdb, out var tmdbId)) { var series = await _tmdbClientManager .GetSeriesAsync(Convert.ToInt32(tmdbId, CultureInfo.InvariantCulture), searchInfo.MetadataLanguage, searchInfo.MetadataLanguage, cancellationToken) @@ -59,9 +57,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV } } - var imdbId = searchInfo.GetProviderId(MetadataProvider.Imdb); - - if (!string.IsNullOrEmpty(imdbId)) + if (searchInfo.TryGetProviderId(MetadataProvider.Imdb, out var imdbId)) { var findResult = await _tmdbClientManager .FindByExternalIdAsync(imdbId, FindExternalSource.Imdb, searchInfo.MetadataLanguage, cancellationToken) @@ -82,9 +78,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV } } - var tvdbId = searchInfo.GetProviderId(MetadataProvider.Tvdb); - - if (!string.IsNullOrEmpty(tvdbId)) + if (searchInfo.TryGetProviderId(MetadataProvider.Tvdb, out var tvdbId)) { var findResult = await _tmdbClientManager .FindByExternalIdAsync(tvdbId, FindExternalSource.TvDb, searchInfo.MetadataLanguage, cancellationToken) @@ -171,33 +165,21 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV var tmdbId = info.GetProviderId(MetadataProvider.Tmdb); - if (string.IsNullOrEmpty(tmdbId)) + if (string.IsNullOrEmpty(tmdbId) && info.TryGetProviderId(MetadataProvider.Imdb, out var imdbId)) { - var imdbId = info.GetProviderId(MetadataProvider.Imdb); - - if (!string.IsNullOrEmpty(imdbId)) + var searchResult = await _tmdbClientManager.FindByExternalIdAsync(imdbId, FindExternalSource.Imdb, info.MetadataLanguage, cancellationToken).ConfigureAwait(false); + if (searchResult?.TvResults.Count > 0) { - var searchResult = await _tmdbClientManager.FindByExternalIdAsync(imdbId, FindExternalSource.Imdb, info.MetadataLanguage, cancellationToken).ConfigureAwait(false); - - if (searchResult != null) - { - tmdbId = searchResult.TvResults.FirstOrDefault()?.Id.ToString(CultureInfo.InvariantCulture); - } + tmdbId = searchResult.TvResults[0].Id.ToString(CultureInfo.InvariantCulture); } } - if (string.IsNullOrEmpty(tmdbId)) + if (string.IsNullOrEmpty(tmdbId) && info.TryGetProviderId(MetadataProvider.Tvdb, out var tvdbId)) { - var tvdbId = info.GetProviderId(MetadataProvider.Tvdb); - - if (!string.IsNullOrEmpty(tvdbId)) + var searchResult = await _tmdbClientManager.FindByExternalIdAsync(tvdbId, FindExternalSource.TvDb, info.MetadataLanguage, cancellationToken).ConfigureAwait(false); + if (searchResult?.TvResults.Count > 0) { - var searchResult = await _tmdbClientManager.FindByExternalIdAsync(tvdbId, FindExternalSource.TvDb, info.MetadataLanguage, cancellationToken).ConfigureAwait(false); - - if (searchResult != null) - { - tmdbId = searchResult.TvResults.FirstOrDefault()?.Id.ToString(CultureInfo.InvariantCulture); - } + tmdbId = searchResult.TvResults[0].Id.ToString(CultureInfo.InvariantCulture); } } @@ -207,7 +189,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV // ParseName is required here. // Caller provides the filename with extension stripped and NOT the parsed filename var parsedName = _libraryManager.ParseName(info.Name); - var searchResults = await _tmdbClientManager.SearchSeriesAsync(parsedName.Name, info.MetadataLanguage, info.Year ?? 0, cancellationToken).ConfigureAwait(false); + var searchResults = await _tmdbClientManager.SearchSeriesAsync(parsedName.Name, info.MetadataLanguage, info.Year ?? parsedName.Year ?? 0, cancellationToken).ConfigureAwait(false); if (searchResults.Count > 0) { @@ -215,32 +197,34 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV } } - if (!string.IsNullOrEmpty(tmdbId)) + if (string.IsNullOrEmpty(tmdbId)) { - cancellationToken.ThrowIfCancellationRequested(); + return result; + } - var tvShow = await _tmdbClientManager - .GetSeriesAsync(Convert.ToInt32(tmdbId, CultureInfo.InvariantCulture), info.MetadataLanguage, TmdbUtils.GetImageLanguagesParam(info.MetadataLanguage), cancellationToken) - .ConfigureAwait(false); + cancellationToken.ThrowIfCancellationRequested(); - result = new MetadataResult<Series> - { - Item = MapTvShowToSeries(tvShow, info.MetadataCountryCode), - ResultLanguage = info.MetadataLanguage ?? tvShow.OriginalLanguage - }; + var tvShow = await _tmdbClientManager + .GetSeriesAsync(Convert.ToInt32(tmdbId, CultureInfo.InvariantCulture), info.MetadataLanguage, TmdbUtils.GetImageLanguagesParam(info.MetadataLanguage), cancellationToken) + .ConfigureAwait(false); - foreach (var person in GetPersons(tvShow)) - { - result.AddPerson(person); - } + result = new MetadataResult<Series> + { + Item = MapTvShowToSeries(tvShow, info.MetadataCountryCode), + ResultLanguage = info.MetadataLanguage ?? tvShow.OriginalLanguage + }; - result.HasMetadata = result.Item != null; + foreach (var person in GetPersons(tvShow)) + { + result.AddPerson(person); } + result.HasMetadata = result.Item != null; + return result; } - private Series MapTvShowToSeries(TvShow seriesResult, string preferredCountryCode) + private static Series MapTvShowToSeries(TvShow seriesResult, string preferredCountryCode) { var series = new Series { @@ -29,9 +29,6 @@ <a href="https://features.jellyfin.org"> <img alt="Submit Feature Requests" src="https://img.shields.io/badge/fider-vote%20on%20features-success.svg"/> </a> -<a href="https://forum.jellyfin.org"> -<img alt="Discuss on our Forum" src="https://img.shields.io/discourse/https/forum.jellyfin.org/users.svg"/> -</a> <a href="https://matrix.to/#/+jellyfin:matrix.org"> <img alt="Chat on Matrix" src="https://img.shields.io/matrix/jellyfin:matrix.org.svg?logo=matrix"/> </a> diff --git a/deployment/Dockerfile.fedora.amd64 b/deployment/Dockerfile.fedora.amd64 index 2549f25ee..137e56ecf 100644 --- a/deployment/Dockerfile.fedora.amd64 +++ b/deployment/Dockerfile.fedora.amd64 @@ -13,9 +13,7 @@ RUN dnf update -y \ && dnf install -y @buildsys-build rpmdevtools git dnf-plugins-core libcurl-devel fontconfig-devel freetype-devel openssl-devel glibc-devel libicu-devel systemd # Install DotNET SDK -RUN rpm --import https://packages.microsoft.com/keys/microsoft.asc \ - && curl -o /etc/yum.repos.d/microsoft-prod.repo https://packages.microsoft.com/config/fedora/$(rpm -E %fedora)/prod.repo \ - && dnf install -y dotnet-sdk-${SDK_VERSION} dotnet-runtime-${SDK_VERSION} +RUN dnf install -y dotnet-sdk-${SDK_VERSION} dotnet-runtime-${SDK_VERSION} # Create symlinks and directories RUN ln -sf ${SOURCE_DIR}/deployment/build.fedora.amd64 /build.sh \ diff --git a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj index a336d2aee..577b61d02 100644 --- a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj +++ b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj @@ -35,11 +35,8 @@ </ItemGroup> <ItemGroup> - <ProjectReference Include="..\..\Jellyfin.Server\Jellyfin.Server.csproj" /> - </ItemGroup> - - <ItemGroup> - <EmbeddedResource Include="TestPage.html" /> + <ProjectReference Include="../../Jellyfin.Api/Jellyfin.Api.csproj" /> + <ProjectReference Include="../../Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj" /> </ItemGroup> </Project> diff --git a/tests/Jellyfin.Api.Tests/Controllers/BrandingControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/BrandingControllerTests.cs index 40933562d..87136dfc8 100644 --- a/tests/Jellyfin.Api.Tests/Controllers/BrandingControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/BrandingControllerTests.cs @@ -1,3 +1,4 @@ +using System.Net; using System.Net.Mime; using System.Text; using System.Text.Json; @@ -5,7 +6,7 @@ using System.Threading.Tasks; using MediaBrowser.Model.Branding; using Xunit; -namespace Jellyfin.Api.Tests +namespace Jellyfin.Server.Integration.Tests { public sealed class BrandingControllerTests : IClassFixture<JellyfinApplicationFactory> { @@ -26,7 +27,7 @@ namespace Jellyfin.Api.Tests var response = await client.GetAsync("/Branding/Configuration"); // Assert - Assert.True(response.IsSuccessStatusCode); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(MediaTypeNames.Application.Json, response.Content.Headers.ContentType?.MediaType); Assert.Equal(Encoding.UTF8.BodyName, response.Content.Headers.ContentType?.CharSet); var responseBody = await response.Content.ReadAsStreamAsync(); diff --git a/tests/Jellyfin.Api.Tests/Controllers/DashboardControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs index 300b2697f..86d6326d8 100644 --- a/tests/Jellyfin.Api.Tests/Controllers/DashboardControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs @@ -8,7 +8,7 @@ using Jellyfin.Api.Models; using MediaBrowser.Common.Json; using Xunit; -namespace Jellyfin.Api.Tests.Controllers +namespace Jellyfin.Server.Integration.Tests.Controllers { public sealed class DashboardControllerTests : IClassFixture<JellyfinApplicationFactory> { @@ -37,9 +37,9 @@ namespace Jellyfin.Api.Tests.Controllers var response = await client.GetAsync("/web/ConfigurationPage?name=TestPlugin").ConfigureAwait(false); - Assert.True(response.IsSuccessStatusCode); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(MediaTypeNames.Text.Html, response.Content.Headers.ContentType?.MediaType); - StreamReader reader = new StreamReader(typeof(TestPlugin).Assembly.GetManifestResourceStream("Jellyfin.Api.Tests.TestPage.html")!); + StreamReader reader = new StreamReader(typeof(TestPlugin).Assembly.GetManifestResourceStream("Jellyfin.Server.Integration.Tests.TestPage.html")!); Assert.Equal(await response.Content.ReadAsStringAsync(), reader.ReadToEnd()); } @@ -60,7 +60,7 @@ namespace Jellyfin.Api.Tests.Controllers var response = await client.GetAsync("/web/ConfigurationPages").ConfigureAwait(false); - Assert.True(response.IsSuccessStatusCode); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); var res = await response.Content.ReadAsStreamAsync(); _ = await JsonSerializer.DeserializeAsync<ConfigurationPageInfo[]>(res, _jsonOpions); @@ -74,7 +74,7 @@ namespace Jellyfin.Api.Tests.Controllers var response = await client.GetAsync("/web/ConfigurationPages?enableInMainMenu=true").ConfigureAwait(false); - Assert.True(response.IsSuccessStatusCode); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(MediaTypeNames.Application.Json, response.Content.Headers.ContentType?.MediaType); Assert.Equal(Encoding.UTF8.BodyName, response.Content.Headers.ContentType?.CharSet); diff --git a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj new file mode 100644 index 000000000..49004966b --- /dev/null +++ b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj @@ -0,0 +1,40 @@ +<Project Sdk="Microsoft.NET.Sdk"> + <PropertyGroup> + <TargetFramework>net5.0</TargetFramework> + <IsPackable>false</IsPackable> + <TreatWarningsAsErrors>true</TreatWarningsAsErrors> + <Nullable>enable</Nullable> + <AnalysisMode>AllEnabledByDefault</AnalysisMode> + <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> + </PropertyGroup> + + <ItemGroup> + <PackageReference Include="AutoFixture" Version="4.15.0" /> + <PackageReference Include="AutoFixture.AutoMoq" Version="4.15.0" /> + <PackageReference Include="AutoFixture.Xunit2" Version="4.15.0" /> + <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="5.0.3" /> + <PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0" /> + <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" /> + <PackageReference Include="xunit" Version="2.4.1" /> + <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" /> + <PackageReference Include="coverlet.collector" Version="3.0.3" /> + <PackageReference Include="Moq" Version="4.16.0" /> + </ItemGroup> + + <!-- Code Analyzers --> + <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> + <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8" PrivateAssets="All" /> + <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> + </ItemGroup> + + <ItemGroup> + <ProjectReference Include="../../Jellyfin.Server/Jellyfin.Server.csproj" /> + </ItemGroup> + + <ItemGroup> + <EmbeddedResource Include="TestPage.html" /> + </ItemGroup> + +</Project> diff --git a/tests/Jellyfin.Api.Tests/JellyfinApplicationFactory.cs b/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs index 92c5495c8..d9ec81a27 100644 --- a/tests/Jellyfin.Api.Tests/JellyfinApplicationFactory.cs +++ b/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs @@ -4,7 +4,6 @@ using System.IO; using System.Threading; using Emby.Server.Implementations; using Emby.Server.Implementations.IO; -using Jellyfin.Server; using MediaBrowser.Common; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Testing; @@ -15,7 +14,7 @@ using Microsoft.Extensions.Logging; using Serilog; using Serilog.Extensions.Logging; -namespace Jellyfin.Api.Tests +namespace Jellyfin.Server.Integration.Tests { /// <summary> /// Factory for bootstrapping the Jellyfin application in memory for functional end to end tests. @@ -26,9 +25,9 @@ namespace Jellyfin.Api.Tests private readonly ConcurrentBag<IDisposable> _disposableComponents = new ConcurrentBag<IDisposable>(); /// <summary> - /// Initializes a new instance of the <see cref="JellyfinApplicationFactory"/> class. + /// Initializes static members of the <see cref="JellyfinApplicationFactory"/> class. /// </summary> - public JellyfinApplicationFactory() + static JellyfinApplicationFactory() { // Perform static initialization that only needs to happen once per test-run Log.Logger = new LoggerConfiguration().WriteTo.Console().CreateLogger(); diff --git a/tests/Jellyfin.Api.Tests/OpenApiSpecTests.cs b/tests/Jellyfin.Server.Integration.Tests/OpenApiSpecTests.cs index 03ab56d1f..3cbd638f9 100644 --- a/tests/Jellyfin.Api.Tests/OpenApiSpecTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/OpenApiSpecTests.cs @@ -6,7 +6,7 @@ using MediaBrowser.Model.Branding; using Xunit; using Xunit.Abstractions; -namespace Jellyfin.Api.Tests +namespace Jellyfin.Server.Integration.Tests { public sealed class OpenApiSpecTests : IClassFixture<JellyfinApplicationFactory> { diff --git a/tests/Jellyfin.Api.Tests/TestAppHost.cs b/tests/Jellyfin.Server.Integration.Tests/TestAppHost.cs index eb4c9b305..4e5d0fcb6 100644 --- a/tests/Jellyfin.Api.Tests/TestAppHost.cs +++ b/tests/Jellyfin.Server.Integration.Tests/TestAppHost.cs @@ -8,7 +8,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -namespace Jellyfin.Api.Tests +namespace Jellyfin.Server.Integration.Tests { /// <summary> /// Implementation of the abstract <see cref="ApplicationHost" /> class. diff --git a/tests/Jellyfin.Api.Tests/TestPage.html b/tests/Jellyfin.Server.Integration.Tests/TestPage.html index 8037af8a6..8037af8a6 100644 --- a/tests/Jellyfin.Api.Tests/TestPage.html +++ b/tests/Jellyfin.Server.Integration.Tests/TestPage.html diff --git a/tests/Jellyfin.Api.Tests/TestPlugin.cs b/tests/Jellyfin.Server.Integration.Tests/TestPlugin.cs index a3b4b6994..1d67ac487 100644 --- a/tests/Jellyfin.Api.Tests/TestPlugin.cs +++ b/tests/Jellyfin.Server.Integration.Tests/TestPlugin.cs @@ -7,7 +7,7 @@ using MediaBrowser.Common.Plugins; using MediaBrowser.Model.Plugins; using MediaBrowser.Model.Serialization; -namespace Jellyfin.Api.Tests +namespace Jellyfin.Server.Integration.Tests { public class TestPlugin : BasePlugin<BasePluginConfiguration>, IHasWebPages { diff --git a/tests/Jellyfin.Api.Tests/TestPluginWithoutPages.cs b/tests/Jellyfin.Server.Integration.Tests/TestPluginWithoutPages.cs index 2d2f78a98..ac10c4784 100644 --- a/tests/Jellyfin.Api.Tests/TestPluginWithoutPages.cs +++ b/tests/Jellyfin.Server.Integration.Tests/TestPluginWithoutPages.cs @@ -6,7 +6,7 @@ using MediaBrowser.Common.Plugins; using MediaBrowser.Model.Plugins; using MediaBrowser.Model.Serialization; -namespace Jellyfin.Api.Tests +namespace Jellyfin.Server.Integration.Tests { public class TestPluginWithoutPages : BasePlugin<BasePluginConfiguration> { diff --git a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj new file mode 100644 index 000000000..65ea28e94 --- /dev/null +++ b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj @@ -0,0 +1,39 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <TargetFramework>net5.0</TargetFramework> + <IsPackable>false</IsPackable> + <TreatWarningsAsErrors>true</TreatWarningsAsErrors> + <Nullable>enable</Nullable> + </PropertyGroup> + + <ItemGroup> + <PackageReference Include="AutoFixture" Version="4.15.0" /> + <PackageReference Include="AutoFixture.AutoMoq" Version="4.15.0" /> + <PackageReference Include="AutoFixture.Xunit2" Version="4.15.0" /> + <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="5.0.3" /> + <PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0" /> + <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" /> + <PackageReference Include="xunit" Version="2.4.1" /> + <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" /> + <PackageReference Include="coverlet.collector" Version="3.0.3" /> + <PackageReference Include="Moq" Version="4.16.0" /> + </ItemGroup> + + <!-- Code Analyzers --> + <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> + <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8" PrivateAssets="All" /> + <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> + </ItemGroup> + + <ItemGroup> + <ProjectReference Include="../../Jellyfin.Server/Jellyfin.Server.csproj" /> + </ItemGroup> + + <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> + <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> + </PropertyGroup> + +</Project> diff --git a/tests/Jellyfin.Api.Tests/ParseNetworkTests.cs b/tests/Jellyfin.Server.Tests/ParseNetworkTests.cs index 3984407ee..0b714e80a 100644 --- a/tests/Jellyfin.Api.Tests/ParseNetworkTests.cs +++ b/tests/Jellyfin.Server.Tests/ParseNetworkTests.cs @@ -10,7 +10,7 @@ using Microsoft.Extensions.Logging.Abstractions; using Moq; using Xunit; -namespace Jellyfin.Api.Tests +namespace Jellyfin.Server.Tests { public class ParseNetworkTests { |
