From f87390e2185fde6b3b6fd6a49e6632bae3d0a448 Mon Sep 17 00:00:00 2001 From: Shadowghost Date: Tue, 15 Sep 2026 11:17:03 -0400 Subject: Backport pull request #18020 from jellyfin/release-12.z Stop the library monitor from refreshing against a disposed host Original-merge: 3aec32cb249ba54a9b6c0c799d2ff84848069722 Merged-by: crobibero Backported-by: Cody Robibero --- .../IO/FileRefresherTests.cs | 57 ++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 tests/Jellyfin.Server.Implementations.Tests/IO/FileRefresherTests.cs (limited to 'tests/Jellyfin.Server.Implementations.Tests/IO/FileRefresherTests.cs') diff --git a/tests/Jellyfin.Server.Implementations.Tests/IO/FileRefresherTests.cs b/tests/Jellyfin.Server.Implementations.Tests/IO/FileRefresherTests.cs new file mode 100644 index 0000000000..fd5f8e4160 --- /dev/null +++ b/tests/Jellyfin.Server.Implementations.Tests/IO/FileRefresherTests.cs @@ -0,0 +1,57 @@ +using System; +using System.IO; +using System.Threading.Tasks; +using Emby.Server.Implementations.IO; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Configuration; +using Microsoft.Extensions.Logging.Abstractions; +using Moq; +using Xunit; + +namespace Jellyfin.Server.Implementations.Tests.IO; + +public class FileRefresherTests +{ + [Fact] + public async Task ProcessPathChanges_PathLookupThrows_StillRefreshesRemainingPaths() + { + var tempDir = Directory.CreateTempSubdirectory("filerefresher"); + try + { + // Ordered so the failing path is dequeued first. + var failingPath = Path.Combine(tempDir.FullName, "failing", "episode.mkv"); + var workingPath = Directory.CreateDirectory(Path.Combine(tempDir.FullName, "working")).FullName; + + var workingItem = new Folder { Path = workingPath, Name = "working" }; + var workingItemFound = new TaskCompletionSource(); + + var libraryManager = new Mock(MockBehavior.Loose); + libraryManager.Setup(x => x.FindByPath(failingPath, null)) + .Throws(new ObjectDisposedException("IServiceProvider")); + libraryManager.Setup(x => x.FindByPath(workingPath, null)) + .Returns(workingItem) + .Callback(() => workingItemFound.TrySetResult()); + + var configurationManager = new Mock(MockBehavior.Loose); + configurationManager.Setup(x => x.Configuration) + .Returns(new ServerConfiguration { LibraryMonitorDelay = 1 }); + + using var refresher = new FileRefresher( + failingPath, + configurationManager.Object, + libraryManager.Object, + NullLogger.Instance); + refresher.AddPath(workingPath); + + await workingItemFound.Task.WaitAsync(TimeSpan.FromSeconds(30), TestContext.Current.CancellationToken); + + libraryManager.Verify(x => x.FindByPath(failingPath, null), Times.Once); + } + finally + { + tempDir.Delete(true); + } + } +} -- cgit v1.2.3