using Emby.Server.Implementations; using Xunit; namespace Jellyfin.Server.Implementations.Tests.Configuration; /// /// The decision ApplicationHost.OnConfigurationUpdated makes about a port change. The ports this /// process bound are fixed for its lifetime and the pending-restart flag is per-process, so an instance /// applying another instance's port change still has to notice its own binding went stale - while leaving /// the authorization write, and the notice that follows it, to the instance that made the change. /// public static class ApplicationHostPortChangeTests { /// /// The local case, unchanged: clear the authorization flag and report the pending restart. /// [Fact] public static void LocalPortChange_ClearsAuthorizationAndRequiresRestart() { var outcome = ApplicationHost.EvaluatePortChange(8096, 8920, 9096, 8920, true, false); Assert.True(outcome.RequiresRestart); Assert.True(outcome.ClearsPortAuthorization); } /// /// The cross-instance case: the peer wrote the new port and cleared the flag with it, so this /// instance must not write, but it is still listening on the old port and has to say so. /// [Theory] [InlineData(true)] [InlineData(false)] public static void RemotePortChange_RequiresRestartWithoutWriting(bool isPortAuthorized) { var outcome = ApplicationHost.EvaluatePortChange(8096, 8920, 9096, 8920, isPortAuthorized, true); Assert.True(outcome.RequiresRestart); Assert.False(outcome.ClearsPortAuthorization); } /// /// A second update while a port change is already pending must not write the flag again, and the /// binding is still stale. /// [Fact] public static void LocalPortChange_WithAuthorizationAlreadyCleared_RequiresRestartWithoutWriting() { var outcome = ApplicationHost.EvaluatePortChange(8096, 8920, 9096, 8920, false, false); Assert.True(outcome.RequiresRestart); Assert.False(outcome.ClearsPortAuthorization); } /// /// An update that leaves the ports alone is not a port change, whoever wrote it. /// [Theory] [InlineData(false)] [InlineData(true)] public static void UnchangedPorts_DoNothing(bool isApplyingRemoteInvalidation) { var outcome = ApplicationHost.EvaluatePortChange(8096, 8920, 8096, 8920, true, isApplyingRemoteInvalidation); Assert.False(outcome.RequiresRestart); Assert.False(outcome.ClearsPortAuthorization); } /// /// Nothing is decided before the ports have been bound. /// [Theory] [InlineData(0, 8920)] [InlineData(8096, 0)] public static void UnboundPorts_DoNothing(int boundHttpPort, int boundHttpsPort) { var outcome = ApplicationHost.EvaluatePortChange(boundHttpPort, boundHttpsPort, 9096, 9920, true, false); Assert.False(outcome.RequiresRestart); Assert.False(outcome.ClearsPortAuthorization); } }