ProviderManagerTests.cs 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using MediaBrowser.Controller.Configuration;
  5. using MediaBrowser.Controller.Entities;
  6. using MediaBrowser.Controller.Entities.Movies;
  7. using MediaBrowser.Controller.Library;
  8. using MediaBrowser.Controller.Providers;
  9. using MediaBrowser.Model.Configuration;
  10. using MediaBrowser.Providers.Manager;
  11. using Microsoft.Extensions.Logging.Abstractions;
  12. using Moq;
  13. using Xunit;
  14. namespace Jellyfin.Providers.Tests.Manager
  15. {
  16. public class ProviderManagerTests
  17. {
  18. private static TheoryData<int, bool[]?, int[]?, int[]?, int?[]?, int[]> GetImageProvidersOrderData()
  19. => new ()
  20. {
  21. { 3, null, null, null, null, new[] { 0, 1, 2 } }, // no order options set
  22. // library options ordering
  23. { 3, null, Array.Empty<int>(), null, null, new[] { 0, 1, 2 } }, // no order provided
  24. { 3, null, new[] { 1 }, null, null, new[] { 1, 0, 2 } }, // one item in order
  25. { 3, null, new[] { 2, 1, 0 }, null, null, new[] { 2, 1, 0 } }, // full reverse order
  26. // server options ordering
  27. { 3, null, null, Array.Empty<int>(), null, new[] { 0, 1, 2 } }, // no order provided
  28. { 3, null, null, new[] { 1 }, null, new[] { 1, 0, 2 } }, // one item in order
  29. { 3, null, null, new[] { 2, 1, 0 }, null, new[] { 2, 1, 0 } }, // full reverse order
  30. // IHasOrder ordering
  31. // TODO unintuitive - default if not IHasOrder is 0, not max
  32. { 3, null, null, null, new int?[] { null, 0, null }, new[] { 0, 1, 2 } }, // one item with order 0, no change because default order value is 0
  33. { 3, null, null, null, new int?[] { null, 1, null }, new[] { 0, 2, 1 } }, // one item in order (goes to end, not beginning)
  34. { 3, null, null, null, new int?[] { 2, 1, 0 }, new[] { 2, 1, 0 } }, // full reverse order
  35. // multiple orders set
  36. // TODO should library fall through to server if both are set on different elements?
  37. { 3, null, new[] { 1 }, new[] { 2, 0, 1 }, null, new[] { 1, 0, 2 } }, // library order first, server order ignored
  38. { 3, null, new[] { 1 }, null, new int?[] { 2, 0, 1 }, new[] { 1, 2, 0 } }, // library order first, then orderby
  39. { 3, null, new[] { 2, 1, 0 }, new[] { 1, 2, 0 }, new int?[] { 2, 0, 1 }, new[] { 2, 1, 0 } }, // library order wins
  40. // ordering with ILocalImageProvider
  41. // TODO what is the value of testing for ILocalImageProvider on the sort, should this be removed? Behavior is unintuitive
  42. { 3, new[] { false, true, false }, new[] { 1, 0, 2 }, null, null, new[] { 0, 2, 1 } }, // ILocalImageProvider - sorts to end even when set first
  43. { 3, new[] { false, true, false }, new[] { 1 }, null, null, new[] { 0, 1, 2 } }, // ILocalImageProvider - set order ignored when only value set
  44. { 2, new[] { true, true }, new[] { 1, 0 }, null, null, new[] { 0, 1 } }, // ILocalImageProvider - set order ignored
  45. { 2, new[] { true, true }, null, null, new int?[] { 1, 0 }, new[] { 1, 0 } }, // ILocalImageProvider - IHasOrder applies
  46. };
  47. [Theory]
  48. [MemberData(nameof(GetImageProvidersOrderData))]
  49. public void GetImageProviders_ProviderOrder_MatchesExpected(int providerCount, bool[]? localImageProvider, int[]? libraryOrder, int[]? serverOrder, int?[]? hasOrderOrder, int[] expectedOrder)
  50. {
  51. var item = new Movie();
  52. var nameProvider = new Func<int, string>(i => "Provider" + i);
  53. var providerList = new List<IImageProvider>();
  54. for (var i = 0; i < providerCount; i++)
  55. {
  56. var order = hasOrderOrder?[i];
  57. if (localImageProvider != null && localImageProvider[i])
  58. {
  59. providerList.Add(MockIImageProvider<ILocalImageProvider>(nameProvider(i), item, order));
  60. }
  61. else
  62. {
  63. providerList.Add(MockIImageProvider<IImageProvider>(nameProvider(i), item, order));
  64. }
  65. }
  66. var libraryOptions = new LibraryOptions();
  67. if (libraryOrder != null)
  68. {
  69. libraryOptions.TypeOptions = new[]
  70. {
  71. new TypeOptions
  72. {
  73. Type = item.GetType().Name,
  74. ImageFetcherOrder = libraryOrder.Select(nameProvider).ToArray()
  75. }
  76. };
  77. }
  78. var serverConfiguration = new ServerConfiguration();
  79. if (serverOrder != null)
  80. {
  81. serverConfiguration.MetadataOptions = new[]
  82. {
  83. new MetadataOptions
  84. {
  85. ItemType = item.GetType().Name,
  86. ImageFetcherOrder = serverOrder.Select(nameProvider).ToArray()
  87. }
  88. };
  89. }
  90. var providerManager = GetProviderManager(serverConfiguration: serverConfiguration, libraryOptions: libraryOptions);
  91. AddParts(providerManager, imageProviders: providerList);
  92. var refreshOptions = new ImageRefreshOptions(Mock.Of<IDirectoryService>(MockBehavior.Strict));
  93. var actualProviders = providerManager.GetImageProviders(item, refreshOptions).ToList();
  94. Assert.Equal(providerList.Count, actualProviders.Count);
  95. for (var i = 0; i < providerList.Count; i++)
  96. {
  97. Assert.Equal(i, actualProviders.IndexOf(providerList[expectedOrder[i]]));
  98. }
  99. }
  100. private static IImageProvider MockIImageProvider<T>(string name, BaseItem supportedType, int? order = null)
  101. where T : class, IImageProvider
  102. {
  103. Mock<IHasOrder>? hasOrder = null;
  104. if (order != null)
  105. {
  106. hasOrder = new Mock<IHasOrder>(MockBehavior.Strict);
  107. hasOrder.Setup(i => i.Order)
  108. .Returns((int)order);
  109. }
  110. var provider = hasOrder == null
  111. ? new Mock<T>(MockBehavior.Strict)
  112. : hasOrder.As<T>();
  113. provider.Setup(p => p.Name)
  114. .Returns(name);
  115. provider.Setup(p => p.Supports(supportedType))
  116. .Returns(true);
  117. return provider.Object;
  118. }
  119. private static ProviderManager GetProviderManager(ServerConfiguration? serverConfiguration = null, LibraryOptions? libraryOptions = null)
  120. {
  121. var serverConfigurationManager = new Mock<IServerConfigurationManager>(MockBehavior.Strict);
  122. serverConfigurationManager.Setup(i => i.Configuration)
  123. .Returns(serverConfiguration ?? new ServerConfiguration());
  124. var libraryManager = new Mock<ILibraryManager>(MockBehavior.Strict);
  125. libraryManager.Setup(i => i.GetLibraryOptions(It.IsAny<BaseItem>()))
  126. .Returns(libraryOptions ?? new LibraryOptions());
  127. var providerManager = new ProviderManager(
  128. null,
  129. null,
  130. serverConfigurationManager.Object,
  131. null,
  132. new NullLogger<ProviderManager>(),
  133. null,
  134. null,
  135. libraryManager.Object,
  136. null);
  137. return providerManager;
  138. }
  139. private static void AddParts(
  140. ProviderManager providerManager,
  141. IEnumerable<IImageProvider>? imageProviders = null,
  142. IEnumerable<IMetadataService>? metadataServices = null,
  143. IEnumerable<IMetadataProvider>? metadataProviders = null,
  144. IEnumerable<IMetadataSaver>? metadataSavers = null,
  145. IEnumerable<IExternalId>? externalIds = null)
  146. {
  147. imageProviders ??= Array.Empty<IImageProvider>();
  148. metadataServices ??= Array.Empty<IMetadataService>();
  149. metadataProviders ??= Array.Empty<IMetadataProvider>();
  150. metadataSavers ??= Array.Empty<IMetadataSaver>();
  151. externalIds ??= Array.Empty<IExternalId>();
  152. providerManager.AddParts(imageProviders, metadataServices, metadataProviders, metadataSavers, externalIds);
  153. }
  154. }
  155. }