mirror of
https://github.com/unclshura/ABStemPlayer.git
synced 2026-08-07 00:43:38 +00:00
170 lines
4.5 KiB
C#
170 lines
4.5 KiB
C#
using AudioCore.Impl;
|
|
|
|
namespace AudioCore_Tests;
|
|
|
|
[TestClass]
|
|
public sealed class BlockingRingBuffer_Tests
|
|
{
|
|
[TestMethod]
|
|
public void WriteAndDrain_Simple()
|
|
{
|
|
var ring = new BlockingRingBuffer(1024);
|
|
var ct = CancellationToken.None;
|
|
|
|
byte[] src = new byte[100];
|
|
for (int i = 0; i < src.Length; i++)
|
|
src[i] = (byte)i;
|
|
|
|
ring.WriteToOutput(src, src.Length, ct);
|
|
|
|
Span<byte> dest = stackalloc byte[100];
|
|
int read = ring.DrainRing(dest, dest.Length);
|
|
|
|
Assert.AreEqual(100, read);
|
|
for (int i = 0; i < 100; i++)
|
|
Assert.AreEqual((byte)i, dest[i]);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Write_WrapAround()
|
|
{
|
|
var ring = new BlockingRingBuffer(32);
|
|
var ct = CancellationToken.None;
|
|
|
|
// Fill almost full
|
|
byte[] first = new byte[20];
|
|
for (int i = 0; i < first.Length; i++)
|
|
first[i] = (byte)(i + 1);
|
|
|
|
ring.WriteToOutput(first, first.Length, ct);
|
|
|
|
// Drain a bit to force wrap
|
|
Span<byte> tmp = stackalloc byte[10];
|
|
int drained = ring.DrainRing(tmp, tmp.Length);
|
|
Assert.AreEqual(10, drained);
|
|
|
|
// Now write again, forcing wrap-around
|
|
byte[] second = new byte[15];
|
|
for (int i = 0; i < second.Length; i++)
|
|
second[i] = (byte)(100 + i);
|
|
|
|
ring.WriteToOutput(second, second.Length, ct);
|
|
|
|
// Drain everything
|
|
Span<byte> dest = stackalloc byte[25];
|
|
int read = ring.DrainRing(dest, dest.Length);
|
|
|
|
Assert.AreEqual(25, read);
|
|
|
|
// First 10 were drained earlier, so remaining 10 from first + 15 from second
|
|
for (int i = 0; i < 10; i++)
|
|
Assert.AreEqual((byte)(i + 11), dest[i]);
|
|
|
|
for (int i = 0; i < 15; i++)
|
|
Assert.AreEqual((byte)(100 + i), dest[10 + i]);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Write_Blocks_WhenFull_And_Unblocks_WhenDrained()
|
|
{
|
|
var ring = new BlockingRingBuffer(64);
|
|
var cts = new CancellationTokenSource();
|
|
|
|
byte[] src = new byte[63]; // fills ring completely (63 bytes free)
|
|
ring.WriteToOutput(src, src.Length, CancellationToken.None);
|
|
|
|
bool writeCompleted = false;
|
|
|
|
var writerThread = new Thread(() =>
|
|
{
|
|
try
|
|
{
|
|
// This should block until space is freed
|
|
ring.WriteToOutput(new byte[10], 10, cts.Token);
|
|
writeCompleted = true;
|
|
}
|
|
catch (OperationCanceledException)
|
|
{
|
|
}
|
|
});
|
|
|
|
writerThread.Start();
|
|
|
|
// Let writer block
|
|
Thread.Sleep(50);
|
|
Assert.IsFalse(writeCompleted, "Writer should be blocked");
|
|
|
|
// Drain some space
|
|
Span<byte> drain = stackalloc byte[20];
|
|
int drained = ring.DrainRing(drain, drain.Length);
|
|
Assert.IsGreaterThan(0, drained);
|
|
|
|
// Writer should now complete
|
|
Thread.Sleep(50);
|
|
Assert.IsTrue(writeCompleted, "Writer should unblock after draining");
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Write_Cancels_WhenFull()
|
|
{
|
|
var ring = new BlockingRingBuffer(32);
|
|
var cts = new CancellationTokenSource();
|
|
|
|
// Fill ring
|
|
ring.WriteToOutput(new byte[31], 31, CancellationToken.None);
|
|
|
|
bool canceled = false;
|
|
|
|
var writerThread = new Thread(() =>
|
|
{
|
|
try
|
|
{
|
|
ring.WriteToOutput(new byte[10], 10, cts.Token);
|
|
}
|
|
catch (OperationCanceledException)
|
|
{
|
|
canceled = true;
|
|
}
|
|
});
|
|
|
|
writerThread.Start();
|
|
|
|
Thread.Sleep(50);
|
|
cts.Cancel();
|
|
|
|
writerThread.Join();
|
|
|
|
Assert.IsTrue(canceled, "Writer should throw OperationCanceledException");
|
|
}
|
|
|
|
[TestMethod]
|
|
public void WaitForOutput_ReturnsAvailable()
|
|
{
|
|
var ring = new BlockingRingBuffer(128);
|
|
var ct = CancellationToken.None;
|
|
|
|
byte[] src = new byte[50];
|
|
ring.WriteToOutput(src, src.Length, ct);
|
|
|
|
int available = ring.WaitForOutput(ct);
|
|
|
|
Assert.AreEqual(50, available);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void ResetRing_ClearsBuffer()
|
|
{
|
|
var ring = new BlockingRingBuffer(128);
|
|
var ct = CancellationToken.None;
|
|
|
|
ring.WriteToOutput(new byte[60], 60, ct);
|
|
|
|
ring.ResetRing();
|
|
|
|
Span<byte> dest = stackalloc byte[128];
|
|
int read = ring.DrainRing(dest, dest.Length);
|
|
|
|
Assert.AreEqual(0, read);
|
|
}
|
|
}
|