AyCode.Core/AyCode.Core.Tests/Serialization/AcBinarySerializerPipeParal...

147 lines
4.8 KiB
C#

using AyCode.Core.Serializers.Binaries;
using static AyCode.Core.Tests.TestModels.AcSerializerModels;
namespace AyCode.Core.Tests.Serialization;
[TestClass]
public class AcBinarySerializerPipeParallelTests
{
[TestMethod]
public async Task SerializeAndDeserialize_InParallelOnTwoTasks_ThroughPipe_RoundTrip()
{
var original = CreatePayload(200);
var options = AcBinarySerializerOptions.Default;
using var reader = new SegmentBufferReader(64);
var deserializeTask = Task.Run(() =>
(TestParentWithDateTimeItemCollection?)AcBinaryDeserializer.Deserialize(reader, typeof(TestParentWithDateTimeItemCollection), options));
var serializeTask = Task.Run(async () =>
{
try
{
var binary = AcBinarySerializer.Serialize(original, options);
var offset = 0;
var chunkSizes = new[] { 7, 31, 13, 64, 5, 29 };
for (var chunkIndex = 0; offset < binary.Length; chunkIndex++)
{
var chunkSize = Math.Min(chunkSizes[chunkIndex % chunkSizes.Length], binary.Length - offset);
reader.Write(binary.AsSpan(offset, chunkSize));
offset += chunkSize;
if (chunkIndex % 4 == 0)
await Task.Yield();
}
}
finally
{
reader.Complete();
}
});
await Task.WhenAll(serializeTask, deserializeTask);
var result = deserializeTask.Result;
Assert.IsNotNull(result);
AssertPayloadEquals(original, result);
}
[TestMethod]
public async Task SerializeAndDeserialize_InParallelOnTwoTasks_WithMultiplePipelines_RoundTrip()
{
var options = AcBinarySerializerOptions.Default;
var pipelines = Enumerable.Range(1, 8).Select(async seed =>
{
var original = CreatePayload(80 + seed * 10);
using var reader = new SegmentBufferReader(32);
var deserializeTask = Task.Run(() =>
(TestParentWithDateTimeItemCollection?)AcBinaryDeserializer.Deserialize(reader, typeof(TestParentWithDateTimeItemCollection), options));
var serializeTask = Task.Run(async () =>
{
try
{
var binary = AcBinarySerializer.Serialize(original, options);
var offset = 0;
var chunkSize = (seed % 5) + 1;
while (offset < binary.Length)
{
var take = Math.Min(chunkSize, binary.Length - offset);
reader.Write(binary.AsSpan(offset, take));
offset += take;
await Task.Yield();
}
}
finally
{
reader.Complete();
}
});
await Task.WhenAll(serializeTask, deserializeTask);
var result = deserializeTask.Result;
Assert.IsNotNull(result);
AssertPayloadEquals(original, result);
});
await Task.WhenAll(pipelines);
}
private static TestParentWithDateTimeItemCollection CreatePayload(int itemCount)
{
var now = DateTime.UtcNow;
var items = new List<TestEntityWithDateTimeAndInt>(itemCount);
for (var i = 0; i < itemCount; i++)
{
items.Add(new TestEntityWithDateTimeAndInt
{
Id = i + 1,
IntValue = i * 3,
Created = now.AddMinutes(-i),
Modified = now.AddMinutes(i),
StatusCode = i % 4,
Name = $"item-{i}"
});
}
return new TestParentWithDateTimeItemCollection
{
Id = 11,
Name = "pipe-parallel-test",
Created = now,
Items = items
};
}
private static void AssertPayloadEquals(TestParentWithDateTimeItemCollection expected, TestParentWithDateTimeItemCollection actual)
{
Assert.AreEqual(expected.Id, actual.Id);
Assert.AreEqual(expected.Name, actual.Name);
Assert.AreEqual(expected.Created, actual.Created);
Assert.IsNotNull(expected.Items);
Assert.IsNotNull(actual.Items);
Assert.AreEqual(expected.Items.Count, actual.Items.Count);
for (var i = 0; i < expected.Items.Count; i++)
{
var e = expected.Items[i];
var a = actual.Items[i];
Assert.AreEqual(e.Id, a.Id);
Assert.AreEqual(e.IntValue, a.IntValue);
Assert.AreEqual(e.Created, a.Created);
Assert.AreEqual(e.Modified, a.Modified);
Assert.AreEqual(e.StatusCode, a.StatusCode);
Assert.AreEqual(e.Name, a.Name);
}
}
}