Files
CydandClaude Fable 5 1ff0b16015 Phase 8A (2/2): RioJoy.Core multi-targets net48 + net40 (Windows XP flavor)
- TargetFrameworks net48;net40. net48 keeps x64 + ViGEm + System.IO.Ports
  package; net40 adds Microsoft.Bcl.Async + System.ValueTuple and uses the
  in-box SerialPort.
- Compat/TaskCompat bridges Task.Run/Delay/WhenAny/WhenAll (TaskEx on
  net40) and SemaphoreSlim.WaitAsync (net40 blocks briefly - trivial at
  9600 baud).
- IReadOnlyList/IReadOnlyDictionary -> IList/IDictionary throughout
  (net40 predates the IReadOnly* interfaces and the Bcl backport cannot
  make arrays implement them).
- HashCode.Combine replaced with a manual combine (Bcl.HashCode has no
  net40 build); Marshal.SizeOf<T> -> typeof form; ViGEmJoystickSink
  gated #if !NET40. HidFeederJoystickSink stays on both flavors - it
  will drive RioGamepadXP.sys on XP via the same contract.

Both TFMs build; 275 tests green on net48.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 20:41:58 -05:00

79 lines
2.5 KiB
C#

using RioJoy.Core.Editing;
using Xunit;
namespace RioJoy.Core.Tests.Editing;
public class SheetLayoutTests
{
[Theory]
[InlineData("0F", 0x0F)]
[InlineData("50", 0x50)]
[InlineData("6F", 0x6F)]
[InlineData("00", 0x00)]
public void AddressFromText_ParsesHexCells(string text, int expected)
{
Assert.Equal(expected, SheetLayout.AddressFromText(text));
}
[Theory]
[InlineData("HOME")]
[InlineData("RIO_0")]
[InlineData("70")] // > 0x6F
[InlineData("M U")]
[InlineData("0")] // single digit
public void AddressFromText_RejectsNonAddresses(string text)
{
Assert.Null(SheetLayout.AddressFromText(text));
}
[Theory]
[InlineData(0x00, SheetSection.Contacts)]
[InlineData(0x10, SheetSection.Secondary)]
[InlineData(0x18, SheetSection.Screen)]
[InlineData(0x2F, SheetSection.Letters)]
[InlineData(0x38, SheetSection.Throttle)]
[InlineData(0x40, SheetSection.Joystick)]
[InlineData(0x50, SheetSection.Keypad)]
[InlineData(0x6F, SheetSection.ExtKeypad)]
public void SectionForAddress_Classifies(int address, SheetSection expected)
{
Assert.Equal(expected, SheetLayout.SectionForAddress(address));
}
[Fact]
public void Parse_BuildsCellsWithGridPositions()
{
const string csv =
"\"\",\"IsLit\",\"\",\"\",\"0F\"\n" +
"\"\",\"\",\"\",\"\",\"HOME\"";
IList<SheetCell> cells = SheetLayout.Parse(csv);
SheetCell addr = Assert.Single(cells, c => c.Text == "0F");
Assert.Equal(0x0F, addr.Address);
Assert.Equal(SheetSection.Contacts, addr.Section);
Assert.Equal(0, addr.Row);
Assert.Equal(4, addr.Col);
SheetCell key = Assert.Single(cells, c => c.Text == "HOME");
Assert.Null(key.Address);
Assert.Equal(1, key.Row);
Assert.Equal(4, key.Col);
}
[Fact]
public void Parse_RealSheet_HasFullAddressMap()
{
IList<SheetCell> cells = SheetLayout.Load(
TestRepo.CustomBackground("config-sheet.csv"));
// Every RIO address 0x00..0x6F that exists should appear exactly once as a cell.
var addresses = cells.Where(c => c.Address is not null).Select(c => c.Address!.Value).ToHashSet();
Assert.Contains(0x00, addresses);
Assert.Contains(0x2F, addresses); // a letter button
Assert.Contains(0x50, addresses); // keypad
Assert.Contains(0x6F, addresses); // ext keypad
Assert.True(addresses.Count >= 100, $"expected most of the address map, got {addresses.Count}");
}
}