ProviderManagerTests.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using MediaBrowser.Controller.BaseItemManager;
  5. using MediaBrowser.Controller.Configuration;
  6. using MediaBrowser.Controller.Entities;
  7. using MediaBrowser.Controller.Entities.Movies;
  8. using MediaBrowser.Controller.Library;
  9. using MediaBrowser.Controller.Providers;
  10. using MediaBrowser.Model.Configuration;
  11. using MediaBrowser.Providers.Manager;
  12. using Microsoft.Extensions.Logging.Abstractions;
  13. using Moq;
  14. using Xunit;
  15. namespace Jellyfin.Providers.Tests.Manager
  16. {
  17. public class ProviderManagerTests
  18. {
  19. private static TheoryData<int, int[]?, int[]?, int?[]?, int[]> GetImageProvidersOrderData()
  20. => new ()
  21. {
  22. { 3, null, null, null, new[] { 0, 1, 2 } }, // no order options set
  23. // library options ordering
  24. { 3, Array.Empty<int>(), null, null, new[] { 0, 1, 2 } }, // no order provided
  25. { 3, new[] { 1 }, null, null, new[] { 1, 0, 2 } }, // one item in order
  26. { 3, new[] { 2, 1, 0 }, null, null, new[] { 2, 1, 0 } }, // full reverse order
  27. // server options ordering
  28. { 3, null, Array.Empty<int>(), null, new[] { 0, 1, 2 } }, // no order provided
  29. { 3, null, new[] { 1 }, null, new[] { 1, 0, 2 } }, // one item in order
  30. { 3, null, new[] { 2, 1, 0 }, null, new[] { 2, 1, 0 } }, // full reverse order
  31. // IHasOrder ordering
  32. { 3, null, null, new int?[] { null, 1, null }, new[] { 1, 0, 2 } }, // one item with defined order
  33. { 3, null, null, new int?[] { 2, 1, 0 }, new[] { 2, 1, 0 } }, // full reverse order
  34. // multiple orders set
  35. { 3, new[] { 1 }, new[] { 2, 0, 1 }, null, new[] { 1, 0, 2 } }, // library order first, server order ignored
  36. { 3, new[] { 1 }, null, new int?[] { 2, 0, 1 }, new[] { 1, 2, 0 } }, // library order first, then orderby
  37. { 3, new[] { 2, 1, 0 }, new[] { 1, 2, 0 }, new int?[] { 2, 0, 1 }, new[] { 2, 1, 0 } }, // library order wins
  38. };
  39. [Theory]
  40. [MemberData(nameof(GetImageProvidersOrderData))]
  41. public void GetImageProviders_ProviderOrder_MatchesExpected(int providerCount, int[]? libraryOrder, int[]? serverOrder, int?[]? hasOrderOrder, int[] expectedOrder)
  42. {
  43. var item = new Movie();
  44. var nameProvider = new Func<int, string>(i => "Provider" + i);
  45. var providerList = new List<IImageProvider>();
  46. for (var i = 0; i < providerCount; i++)
  47. {
  48. var order = hasOrderOrder?[i];
  49. providerList.Add(MockIImageProvider<IImageProvider>(nameProvider(i), item, order: order));
  50. }
  51. var libraryOptions = new LibraryOptions();
  52. if (libraryOrder != null)
  53. {
  54. libraryOptions.TypeOptions = new[]
  55. {
  56. new TypeOptions
  57. {
  58. Type = item.GetType().Name,
  59. ImageFetcherOrder = libraryOrder.Select(nameProvider).ToArray()
  60. }
  61. };
  62. }
  63. var serverConfiguration = new ServerConfiguration();
  64. if (serverOrder != null)
  65. {
  66. serverConfiguration.MetadataOptions = new[]
  67. {
  68. new MetadataOptions
  69. {
  70. ItemType = item.GetType().Name,
  71. ImageFetcherOrder = serverOrder.Select(nameProvider).ToArray()
  72. }
  73. };
  74. }
  75. var providerManager = GetProviderManager(serverConfiguration: serverConfiguration, libraryOptions: libraryOptions);
  76. AddParts(providerManager, imageProviders: providerList);
  77. var refreshOptions = new ImageRefreshOptions(Mock.Of<IDirectoryService>(MockBehavior.Strict));
  78. var actualProviders = providerManager.GetImageProviders(item, refreshOptions).ToList();
  79. Assert.Equal(providerList.Count, actualProviders.Count);
  80. for (var i = 0; i < providerList.Count; i++)
  81. {
  82. Assert.Equal(i, actualProviders.IndexOf(providerList[expectedOrder[i]]));
  83. }
  84. }
  85. [Theory]
  86. [InlineData(true, false, true)]
  87. [InlineData(false, false, false)]
  88. [InlineData(true, true, false)]
  89. public void GetImageProviders_CanRefreshBasic_WhenSupportsWithoutError(bool supports, bool errorOnSupported, bool expected)
  90. {
  91. GetImageProviders_CanRefresh_Tester(typeof(IImageProvider), supports, expected, errorOnSupported: errorOnSupported);
  92. }
  93. [Theory]
  94. [InlineData(typeof(ILocalImageProvider), false, true)]
  95. [InlineData(typeof(ILocalImageProvider), true, true)]
  96. [InlineData(typeof(IImageProvider), false, false)]
  97. [InlineData(typeof(IImageProvider), true, true)]
  98. public void GetImageProviders_CanRefreshLocked_WhenLocalOrFullRefresh(Type providerType, bool fullRefresh, bool expected)
  99. {
  100. GetImageProviders_CanRefresh_Tester(providerType, true, expected, itemLocked: true, fullRefresh: fullRefresh);
  101. }
  102. [Theory]
  103. [InlineData(typeof(ILocalImageProvider), false, true)]
  104. [InlineData(typeof(IRemoteImageProvider), true, true)]
  105. [InlineData(typeof(IDynamicImageProvider), true, true)]
  106. [InlineData(typeof(IRemoteImageProvider), false, false)]
  107. [InlineData(typeof(IDynamicImageProvider), false, false)]
  108. public void GetImageProviders_CanRefreshEnabled_WhenLocalOrEnabled(Type providerType, bool enabled, bool expected)
  109. {
  110. GetImageProviders_CanRefresh_Tester(providerType, true, expected, baseItemEnabled: enabled);
  111. }
  112. private static void GetImageProviders_CanRefresh_Tester(Type providerType, bool supports, bool expected, bool errorOnSupported = false, bool itemLocked = false, bool fullRefresh = false, bool baseItemEnabled = true)
  113. {
  114. var item = new Movie
  115. {
  116. IsLocked = itemLocked
  117. };
  118. var providerName = "provider";
  119. IImageProvider provider = providerType.Name switch
  120. {
  121. "IImageProvider" => MockIImageProvider<IImageProvider>(providerName, item, supports: supports, errorOnSupported: errorOnSupported),
  122. "ILocalImageProvider" => MockIImageProvider<ILocalImageProvider>(providerName, item, supports: supports, errorOnSupported: errorOnSupported),
  123. "IRemoteImageProvider" => MockIImageProvider<IRemoteImageProvider>(providerName, item, supports: supports, errorOnSupported: errorOnSupported),
  124. "IDynamicImageProvider" => MockIImageProvider<IDynamicImageProvider>(providerName, item, supports: supports, errorOnSupported: errorOnSupported),
  125. _ => throw new ArgumentException("Unexpected provider type")
  126. };
  127. var refreshOptions = new ImageRefreshOptions(Mock.Of<IDirectoryService>(MockBehavior.Strict))
  128. {
  129. ImageRefreshMode = fullRefresh ? MetadataRefreshMode.FullRefresh : MetadataRefreshMode.Default
  130. };
  131. var baseItemManager = new Mock<IBaseItemManager>(MockBehavior.Strict);
  132. baseItemManager.Setup(i => i.IsImageFetcherEnabled(item, It.IsAny<LibraryOptions>(), providerName))
  133. .Returns(baseItemEnabled);
  134. var providerManager = GetProviderManager(baseItemManager: baseItemManager.Object);
  135. AddParts(providerManager, imageProviders: new[] { provider });
  136. var actualProviders = providerManager.GetImageProviders(item, refreshOptions);
  137. if (expected)
  138. {
  139. Assert.Single(actualProviders);
  140. }
  141. else
  142. {
  143. Assert.Empty(actualProviders);
  144. }
  145. }
  146. private static IImageProvider MockIImageProvider<T>(string name, BaseItem expectedType, bool supports = true, int? order = null, bool errorOnSupported = false)
  147. where T : class, IImageProvider
  148. {
  149. Mock<IHasOrder>? hasOrder = null;
  150. if (order != null)
  151. {
  152. hasOrder = new Mock<IHasOrder>(MockBehavior.Strict);
  153. hasOrder.Setup(i => i.Order)
  154. .Returns((int)order);
  155. }
  156. var provider = hasOrder == null
  157. ? new Mock<T>(MockBehavior.Strict)
  158. : hasOrder.As<T>();
  159. provider.Setup(p => p.Name)
  160. .Returns(name);
  161. if (errorOnSupported)
  162. {
  163. provider.Setup(p => p.Supports(It.IsAny<BaseItem>()))
  164. .Throws(new ArgumentException());
  165. }
  166. else
  167. {
  168. provider.Setup(p => p.Supports(expectedType))
  169. .Returns(supports);
  170. }
  171. return provider.Object;
  172. }
  173. private static ProviderManager GetProviderManager(ServerConfiguration? serverConfiguration = null, LibraryOptions? libraryOptions = null, IBaseItemManager? baseItemManager = null)
  174. {
  175. var serverConfigurationManager = new Mock<IServerConfigurationManager>(MockBehavior.Strict);
  176. serverConfigurationManager.Setup(i => i.Configuration)
  177. .Returns(serverConfiguration ?? new ServerConfiguration());
  178. var libraryManager = new Mock<ILibraryManager>(MockBehavior.Strict);
  179. libraryManager.Setup(i => i.GetLibraryOptions(It.IsAny<BaseItem>()))
  180. .Returns(libraryOptions ?? new LibraryOptions());
  181. var providerManager = new ProviderManager(
  182. null,
  183. null,
  184. serverConfigurationManager.Object,
  185. null,
  186. new NullLogger<ProviderManager>(),
  187. null,
  188. null,
  189. libraryManager.Object,
  190. baseItemManager);
  191. return providerManager;
  192. }
  193. private static void AddParts(
  194. ProviderManager providerManager,
  195. IEnumerable<IImageProvider>? imageProviders = null,
  196. IEnumerable<IMetadataService>? metadataServices = null,
  197. IEnumerable<IMetadataProvider>? metadataProviders = null,
  198. IEnumerable<IMetadataSaver>? metadataSavers = null,
  199. IEnumerable<IExternalId>? externalIds = null)
  200. {
  201. imageProviders ??= Array.Empty<IImageProvider>();
  202. metadataServices ??= Array.Empty<IMetadataService>();
  203. metadataProviders ??= Array.Empty<IMetadataProvider>();
  204. metadataSavers ??= Array.Empty<IMetadataSaver>();
  205. externalIds ??= Array.Empty<IExternalId>();
  206. providerManager.AddParts(imageProviders, metadataServices, metadataProviders, metadataSavers, externalIds);
  207. }
  208. }
  209. }