192 lines
7.2 KiB
C#
192 lines
7.2 KiB
C#
using System;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using AutoFixture;
|
|
using AutoFixture.AutoMoq;
|
|
using Emby.Server.Implementations.QuickConnect;
|
|
using MediaBrowser.Common.Extensions;
|
|
using MediaBrowser.Controller.Authentication;
|
|
using MediaBrowser.Controller.Configuration;
|
|
using MediaBrowser.Controller.Net;
|
|
using MediaBrowser.Controller.QuickConnect;
|
|
using MediaBrowser.Model.Configuration;
|
|
using Moq;
|
|
using Xunit;
|
|
|
|
namespace Jellyfin.Server.Implementations.Tests.QuickConnect
|
|
{
|
|
public class QuickConnectManagerTests
|
|
{
|
|
private static readonly AuthorizationInfo _quickConnectAuthInfo = new AuthorizationInfo
|
|
{
|
|
Device = "Device",
|
|
DeviceId = "DeviceId",
|
|
Client = "Client",
|
|
Version = "1.0.0"
|
|
};
|
|
|
|
private readonly Fixture _fixture;
|
|
private readonly ServerConfiguration _config;
|
|
private readonly QuickConnectManager _quickConnectManager;
|
|
|
|
public QuickConnectManagerTests()
|
|
{
|
|
_config = new ServerConfiguration();
|
|
var configManager = new Mock<IServerConfigurationManager>();
|
|
configManager.Setup(x => x.Configuration).Returns(_config);
|
|
|
|
_fixture = new Fixture();
|
|
_fixture.Customize(new AutoMoqCustomization
|
|
{
|
|
ConfigureMembers = true
|
|
}).Inject(configManager.Object);
|
|
|
|
_fixture.Inject<IQuickConnectStore>(new InMemoryQuickConnectStore());
|
|
|
|
// User object contains circular references.
|
|
_fixture.Behaviors.OfType<ThrowingRecursionBehavior>().ToList()
|
|
.ForEach(b => _fixture.Behaviors.Remove(b));
|
|
_fixture.Behaviors.Add(new OmitOnRecursionBehavior());
|
|
|
|
_quickConnectManager = _fixture.Create<QuickConnectManager>();
|
|
}
|
|
|
|
[Fact]
|
|
public void IsEnabled_QuickConnectUnavailable_False()
|
|
{
|
|
_config.QuickConnectAvailable = false;
|
|
Assert.False(_quickConnectManager.IsEnabled);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData("", "DeviceId", "Client", "1.0.0")]
|
|
[InlineData("Device", "", "Client", "1.0.0")]
|
|
[InlineData("Device", "DeviceId", "", "1.0.0")]
|
|
[InlineData("Device", "DeviceId", "Client", "")]
|
|
public async Task TryConnect_InvalidAuthorizationInfo_ThrowsArgumentException(string device, string deviceId, string client, string version)
|
|
=> await Assert.ThrowsAsync<ArgumentException>(() => _quickConnectManager.TryConnect(
|
|
new AuthorizationInfo
|
|
{
|
|
Device = device,
|
|
DeviceId = deviceId,
|
|
Client = client,
|
|
Version = version
|
|
}));
|
|
|
|
[Fact]
|
|
public async Task TryConnect_QuickConnectUnavailable_ThrowsAuthenticationException()
|
|
{
|
|
_config.QuickConnectAvailable = false;
|
|
await Assert.ThrowsAsync<AuthenticationException>(() => _quickConnectManager.TryConnect(_quickConnectAuthInfo));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task CheckRequestStatus_QuickConnectUnavailable_ThrowsAuthenticationException()
|
|
{
|
|
_config.QuickConnectAvailable = false;
|
|
await Assert.ThrowsAsync<AuthenticationException>(() => _quickConnectManager.CheckRequestStatus(string.Empty));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task AuthorizeRequest_QuickConnectUnavailable_ThrowsAuthenticationException()
|
|
{
|
|
_config.QuickConnectAvailable = false;
|
|
await Assert.ThrowsAsync<AuthenticationException>(() => _quickConnectManager.AuthorizeRequest(Guid.Empty, string.Empty));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetAuthorizedRequest_QuickConnectUnavailable_ThrowsAuthenticationException()
|
|
{
|
|
_config.QuickConnectAvailable = false;
|
|
await Assert.ThrowsAsync<AuthenticationException>(() => _quickConnectManager.GetAuthorizedRequest(string.Empty));
|
|
}
|
|
|
|
[Fact]
|
|
public void IsEnabled_QuickConnectAvailable_True()
|
|
{
|
|
_config.QuickConnectAvailable = true;
|
|
Assert.True(_quickConnectManager.IsEnabled);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task CheckRequestStatus_QuickConnectAvailable_Success()
|
|
{
|
|
_config.QuickConnectAvailable = true;
|
|
var res1 = await _quickConnectManager.TryConnect(_quickConnectAuthInfo);
|
|
var res2 = await _quickConnectManager.CheckRequestStatus(res1.Secret);
|
|
Assert.Equal(res1.Secret, res2.Secret);
|
|
Assert.Equal(res1.Code, res2.Code);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task CheckRequestStatus_UnknownSecret_ThrowsResourceNotFoundException()
|
|
{
|
|
_config.QuickConnectAvailable = true;
|
|
await Assert.ThrowsAsync<ResourceNotFoundException>(() => _quickConnectManager.CheckRequestStatus("Unknown secret"));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetAuthorizedRequest_UnknownSecret_ThrowsResourceNotFoundException()
|
|
{
|
|
_config.QuickConnectAvailable = true;
|
|
await Assert.ThrowsAsync<ResourceNotFoundException>(() => _quickConnectManager.GetAuthorizedRequest("Unknown secret"));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task AuthorizeRequest_QuickConnectAvailable_Success()
|
|
{
|
|
_config.QuickConnectAvailable = true;
|
|
var res = await _quickConnectManager.TryConnect(_quickConnectAuthInfo);
|
|
Assert.True(await _quickConnectManager.AuthorizeRequest(Guid.Empty, res.Code));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task AuthorizeRequest_RacedOnOneCode_SucceedsOnce()
|
|
{
|
|
_config.QuickConnectAvailable = true;
|
|
var res = await _quickConnectManager.TryConnect(_quickConnectAuthInfo);
|
|
|
|
var outcomes = await Task.WhenAll(
|
|
Task.Run(() => AuthorizeAsync(res.Code)),
|
|
Task.Run(() => AuthorizeAsync(res.Code)));
|
|
|
|
Assert.Single(outcomes, authorized => authorized);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetAuthorizedRequest_SecondExchange_ReturnsTheSameResult()
|
|
{
|
|
_config.QuickConnectAvailable = true;
|
|
var res = await _quickConnectManager.TryConnect(_quickConnectAuthInfo);
|
|
await _quickConnectManager.AuthorizeRequest(Guid.Empty, res.Code);
|
|
|
|
var first = await _quickConnectManager.GetAuthorizedRequest(res.Secret);
|
|
var second = await _quickConnectManager.GetAuthorizedRequest(res.Secret);
|
|
|
|
Assert.Same(first, second);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task AuthorizeRequest_OfAnAuthorizedRequest_ThrowsConflictException()
|
|
{
|
|
_config.QuickConnectAvailable = true;
|
|
var res = await _quickConnectManager.TryConnect(_quickConnectAuthInfo);
|
|
await _quickConnectManager.AuthorizeRequest(Guid.Empty, res.Code);
|
|
|
|
await Assert.ThrowsAsync<ConflictException>(() => _quickConnectManager.AuthorizeRequest(Guid.Empty, res.Code));
|
|
}
|
|
|
|
private async Task<bool> AuthorizeAsync(string code)
|
|
{
|
|
try
|
|
{
|
|
return await _quickConnectManager.AuthorizeRequest(Guid.Empty, code).ConfigureAwait(false);
|
|
}
|
|
catch (ConflictException)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|