141 lines
3.8 KiB
C#
141 lines
3.8 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Text;
|
|
using Xunit;
|
|
|
|
namespace Server.Tests;
|
|
|
|
public class FileBufferWriterTests
|
|
{
|
|
private static string TempFile() =>
|
|
Path.Combine(Path.GetTempPath(), $"muo-fbw-{Guid.NewGuid():N}.bin");
|
|
|
|
[Fact]
|
|
public void DrainsAcrossStagingBoundariesAndPatchesBackwards()
|
|
{
|
|
var path = TempFile();
|
|
|
|
try
|
|
{
|
|
// Tiny staging block so every few records cross a drain; mirrors the idx
|
|
// pattern: version, count placeholder, records, backwards count patch.
|
|
using (var writer = new FileBufferWriter(path, expectedSize: 64))
|
|
{
|
|
writer.Write(3); // version
|
|
|
|
var countPosition = writer.Position;
|
|
writer.Write(0);
|
|
|
|
const int records = 1000;
|
|
for (var i = 0; i < records; i++)
|
|
{
|
|
writer.Write((ulong)i * 0x9E3779B97F4A7C15);
|
|
writer.Write(i);
|
|
}
|
|
|
|
var end = writer.Position;
|
|
writer.Seek(countPosition, SeekOrigin.Begin);
|
|
writer.Write(records);
|
|
writer.Seek(0, SeekOrigin.End);
|
|
|
|
Assert.Equal(end, writer.Position);
|
|
}
|
|
|
|
var bytes = File.ReadAllBytes(path);
|
|
Assert.Equal(4 + 4 + 1000 * 12, bytes.Length);
|
|
|
|
IGenericReader reader = new BufferReader(bytes);
|
|
Assert.Equal(3, reader.ReadInt());
|
|
Assert.Equal(1000, reader.ReadInt());
|
|
|
|
for (var i = 0; i < 1000; i++)
|
|
{
|
|
Assert.Equal((ulong)i * 0x9E3779B97F4A7C15, reader.ReadULong());
|
|
Assert.Equal(i, reader.ReadInt());
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
File.Delete(path);
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void OversizedSingleItemGrowsTheStagingBlock()
|
|
{
|
|
var path = TempFile();
|
|
|
|
try
|
|
{
|
|
// A string whose worst-case reservation exceeds the staging block must grow
|
|
// the block instead of deadlocking the drain loop.
|
|
var value = new string('二', 500); // 1500 bytes utf8, staging 64
|
|
|
|
using (var writer = new FileBufferWriter(path, expectedSize: 64))
|
|
{
|
|
writer.Write(value);
|
|
writer.Write(0xC0FFEE);
|
|
}
|
|
|
|
IGenericReader reader = new BufferReader(File.ReadAllBytes(path));
|
|
Assert.Equal(value, reader.ReadString());
|
|
Assert.Equal(0xC0FFEE, reader.ReadInt());
|
|
}
|
|
finally
|
|
{
|
|
File.Delete(path);
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void SpanWritesCrossDrains()
|
|
{
|
|
var path = TempFile();
|
|
|
|
try
|
|
{
|
|
var payload = new byte[777];
|
|
new System.Random(0x5EED).NextBytes(payload);
|
|
|
|
using (var writer = new FileBufferWriter(path, expectedSize: 64))
|
|
{
|
|
writer.Write((ReadOnlySpan<byte>)payload);
|
|
}
|
|
|
|
Assert.Equal(payload, File.ReadAllBytes(path));
|
|
}
|
|
finally
|
|
{
|
|
File.Delete(path);
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void TypeWritesRegisterIntoTheTypeSet()
|
|
{
|
|
var path = TempFile();
|
|
|
|
try
|
|
{
|
|
var typeSet = new System.Collections.Generic.HashSet<Type>();
|
|
|
|
using (var writer = new FileBufferWriter(path, typeSet))
|
|
{
|
|
writer.Write(typeof(string));
|
|
writer.Write((Type)null);
|
|
}
|
|
|
|
Assert.Contains(typeof(string), typeSet);
|
|
Assert.Single(typeSet);
|
|
|
|
var bytes = File.ReadAllBytes(path);
|
|
Assert.Equal(1 + 8 + 1, bytes.Length); // flag + hash + null flag
|
|
Assert.Equal(2, bytes[0]);
|
|
Assert.Equal(0, bytes[^1]);
|
|
}
|
|
finally
|
|
{
|
|
File.Delete(path);
|
|
}
|
|
}
|
|
}
|