123 lines
3.6 KiB
C#
123 lines
3.6 KiB
C#
using Xunit;
|
|
using ytLive.Services;
|
|
|
|
namespace ytLive.Tests;
|
|
|
|
public class CameraManagerTests
|
|
{
|
|
private sealed class FakeFrameSource : ICameraFrameSource
|
|
{
|
|
private readonly List<string> _started;
|
|
private readonly List<string> _stopped;
|
|
|
|
public string DeviceId { get; }
|
|
public event Action<VideoFrame>? FrameAvailable;
|
|
|
|
public FakeFrameSource(string deviceId, List<string> started, List<string> stopped)
|
|
{
|
|
DeviceId = deviceId;
|
|
_started = started;
|
|
_stopped = stopped;
|
|
}
|
|
|
|
public Task StartAsync()
|
|
{
|
|
_started.Add(DeviceId);
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task StopAsync()
|
|
{
|
|
_stopped.Add(DeviceId);
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public void Pump(VideoFrame frame) => FrameAvailable?.Invoke(frame);
|
|
}
|
|
|
|
private sealed class FailingFrameSource : ICameraFrameSource
|
|
{
|
|
public string DeviceId { get; }
|
|
public event Action<VideoFrame>? FrameAvailable;
|
|
public bool Stopped;
|
|
|
|
public FailingFrameSource(string deviceId) => DeviceId = deviceId;
|
|
|
|
public Task StartAsync() => throw new InvalidOperationException("camera in use");
|
|
|
|
public Task StopAsync()
|
|
{
|
|
Stopped = true;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public void Pump(VideoFrame frame) => FrameAvailable?.Invoke(frame);
|
|
}
|
|
|
|
private static CameraManager CreateManager(List<string> started, List<string> stopped)
|
|
=> new(new FakeEnumerator(), id => new FakeFrameSource(id, started, stopped));
|
|
|
|
private sealed class FakeEnumerator : ICameraEnumerator
|
|
{
|
|
public Task<IReadOnlyList<CameraDeviceInfo>> GetCamerasAsync()
|
|
=> Task.FromResult<IReadOnlyList<CameraDeviceInfo>>(new[]
|
|
{
|
|
new CameraDeviceInfo("dev1", "Logitech C920"),
|
|
});
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Refcount_TwoAcquires_OneCaptureUntilLastRelease()
|
|
{
|
|
var started = new List<string>();
|
|
var stopped = new List<string>();
|
|
var manager = CreateManager(started, stopped);
|
|
|
|
Assert.True(await manager.AcquireAsync("dev1"));
|
|
Assert.True(await manager.AcquireAsync("dev1"));
|
|
Assert.Single(started);
|
|
|
|
await manager.ReleaseAsync("dev1");
|
|
Assert.Empty(stopped);
|
|
|
|
await manager.ReleaseAsync("dev1");
|
|
Assert.Single(stopped);
|
|
Assert.Null(manager.GetLatestFrame("dev1"));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task FramePump_UpdatesLatestFrame()
|
|
{
|
|
var started = new List<string>();
|
|
var stopped = new List<string>();
|
|
FakeFrameSource? captured = null;
|
|
var manager = new CameraManager(
|
|
new FakeEnumerator(),
|
|
id => captured = new FakeFrameSource(id, started, stopped));
|
|
|
|
await manager.AcquireAsync("dev1");
|
|
var frame = new VideoFrame(2, 2, new byte[16]);
|
|
captured!.Pump(frame);
|
|
|
|
Assert.Same(frame, manager.GetLatestFrame("dev1"));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Acquire_FailingCamera_ReturnsFalseAndStops()
|
|
{
|
|
var manager = new CameraManager(new FakeEnumerator(), id => new FailingFrameSource(id));
|
|
string? failedDevice = null;
|
|
manager.CameraFailed += (device, _) => failedDevice = device;
|
|
|
|
Assert.False(await manager.AcquireAsync("dev1"));
|
|
Assert.Equal("dev1", failedDevice);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Acquire_EmptyDeviceId_ReturnsFalse()
|
|
{
|
|
var manager = CreateManager(new List<string>(), new List<string>());
|
|
Assert.False(await manager.AcquireAsync(" "));
|
|
}
|
|
}
|