sharpemu/tests/SharpEmu.Libs.Tests/Kernel/KernelPosixSocketOptionTest...

110 lines
3.7 KiB
C#

// Copyright (C) 2026 SharpEmu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
using System.Buffers.Binary;
using SharpEmu.HLE;
using SharpEmu.Libs.Kernel;
using SharpEmu.Libs.Network;
using Xunit;
namespace SharpEmu.Libs.Tests.Kernel;
public sealed class KernelPosixSocketOptionTests
{
private const ulong BaseAddress = 0x1_0000_0000;
private const ulong ValueAddress = BaseAddress + 0x100;
private const ulong LengthAddress = BaseAddress + 0x200;
[Theory]
[InlineData(28, 41, 27, 1)]
[InlineData(2, 0xFFFF, 0x20, 1)]
[InlineData(2, 0xFFFF, 0x1002, 262144)]
public void PosixSetAndGetSocketOption_UsesKernelSocketDescriptor(
int family,
int level,
int option,
int expectedValue)
{
var memory = new FakeCpuMemory(BaseAddress, 0x1000);
var ctx = new CpuContext(memory, Generation.Gen5);
var fd = CreateDatagramSocket(ctx, family);
try
{
WriteInt32(memory, ValueAddress, expectedValue);
ctx[CpuRegister.Rdi] = unchecked((uint)fd);
ctx[CpuRegister.Rsi] = unchecked((uint)level);
ctx[CpuRegister.Rdx] = unchecked((uint)option);
ctx[CpuRegister.Rcx] = ValueAddress;
ctx[CpuRegister.R8] = sizeof(int);
Assert.Equal(0, NetExports.PosixSetsockopt(ctx));
Assert.Equal(0UL, ctx[CpuRegister.Rax]);
WriteInt32(memory, ValueAddress, 0);
WriteInt32(memory, LengthAddress, sizeof(int));
ctx[CpuRegister.Rdi] = unchecked((uint)fd);
ctx[CpuRegister.Rsi] = unchecked((uint)level);
ctx[CpuRegister.Rdx] = unchecked((uint)option);
ctx[CpuRegister.Rcx] = ValueAddress;
ctx[CpuRegister.R8] = LengthAddress;
Assert.Equal(0, NetExports.PosixGetsockopt(ctx));
Assert.Equal(expectedValue, ReadInt32(memory, ValueAddress));
Assert.Equal(sizeof(int), ReadInt32(memory, LengthAddress));
}
finally
{
KernelSocketCompatExports.TryCloseSocketFd(fd);
}
}
[Fact]
public void PosixSetSocketOption_RejectsUnknownOptionOnKnownDescriptor()
{
var memory = new FakeCpuMemory(BaseAddress, 0x1000);
var ctx = new CpuContext(memory, Generation.Gen5);
var fd = CreateDatagramSocket(ctx, 2);
try
{
WriteInt32(memory, ValueAddress, 1);
ctx[CpuRegister.Rdi] = unchecked((uint)fd);
ctx[CpuRegister.Rsi] = 0xFFFF;
ctx[CpuRegister.Rdx] = 2;
ctx[CpuRegister.Rcx] = ValueAddress;
ctx[CpuRegister.R8] = sizeof(int);
Assert.Equal(-1, NetExports.PosixSetsockopt(ctx));
Assert.Equal(ulong.MaxValue, ctx[CpuRegister.Rax]);
}
finally
{
KernelSocketCompatExports.TryCloseSocketFd(fd);
}
}
private static int CreateDatagramSocket(CpuContext ctx, int family)
{
ctx[CpuRegister.Rdi] = unchecked((uint)family);
ctx[CpuRegister.Rsi] = 2;
ctx[CpuRegister.Rdx] = 0;
Assert.Equal(0, KernelSocketCompatExports.Socket(ctx));
return checked((int)ctx[CpuRegister.Rax]);
}
private static void WriteInt32(FakeCpuMemory memory, ulong address, int value)
{
Span<byte> bytes = stackalloc byte[sizeof(int)];
BinaryPrimitives.WriteInt32LittleEndian(bytes, value);
Assert.True(memory.TryWrite(address, bytes));
}
private static int ReadInt32(FakeCpuMemory memory, ulong address)
{
Span<byte> bytes = stackalloc byte[sizeof(int)];
Assert.True(memory.TryRead(address, bytes));
return BinaryPrimitives.ReadInt32LittleEndian(bytes);
}
}