using System.Collections.Generic; using Jellyfin.Server.Extensions; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Session; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging.Abstractions; using Moq; using StackExchange.Redis; using Xunit; namespace Jellyfin.Server.Tests.HighAvailability; /// /// The directory and the bus are two halves of one mechanism: a shared directory paired with a bus that /// reaches nobody advertises sessions from every instance and then fails every command sent to one. /// public static class SessionDirectoryRegistrationTests { [Fact] public static void AddSessionDirectory_WithoutARedisConnection_RegistersNeitherHalf() { var services = Build(configured: false); Assert.IsType(services.GetRequiredService()); Assert.IsType(services.GetRequiredService()); } [Fact] public static void AddSessionDirectory_WhenOneHalfCannotBeBuilt_FallsBackOnBoth() { // A connection that can serve the directory but not the bus: taking the directory on its own // would advertise every instance's sessions and then fail every command sent to one. var redis = new Mock(); redis.Setup(i => i.GetDatabase(It.IsAny(), It.IsAny())).Returns(Mock.Of()); redis.Setup(i => i.GetSubscriber(It.IsAny())).Throws(new RedisConnectionException(ConnectionFailureType.UnableToConnect, "unreachable")); var services = Build(configured: true, redis.Object); Assert.IsType(services.GetRequiredService()); Assert.IsType(services.GetRequiredService()); } private static ServiceProvider Build(bool configured, IConnectionMultiplexer? redis = null) { var settings = new Dictionary(); if (configured) { settings[TranscodeStoreOptions.RedisConnectionStringKey] = "127.0.0.1:6379"; } var configuration = new ConfigurationBuilder().AddInMemoryCollection(settings).Build(); var serviceCollection = new ServiceCollection().AddLogging(); if (redis is not null) { serviceCollection.AddSingleton(redis); } return serviceCollection .AddSessionDirectory(configuration, NullLogger.Instance) .BuildServiceProvider(); } }