- 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>
69 lines
2.6 KiB
C#
69 lines
2.6 KiB
C#
using RioJoy.Core.Editing;
|
||
using RioJoy.Core.Mapping;
|
||
using Xunit;
|
||
|
||
namespace RioJoy.Core.Tests.Editing;
|
||
|
||
public class CockpitPanelTests
|
||
{
|
||
[Fact]
|
||
public void Covers_EveryValidAddress_ExactlyOnce()
|
||
{
|
||
List<int> addrs = CockpitPanel.Buttons().Select(b => b.Address).ToList();
|
||
|
||
// 0x00–0x47 buttons + 0x50–0x6F keypads = 104 valid addresses; 0x48–0x4F don't exist.
|
||
var expected = Enumerable.Range(0x00, 0x48).Concat(Enumerable.Range(0x50, 0x20)).ToHashSet();
|
||
Assert.Equal(expected.Count, addrs.Count); // no duplicates / no extras
|
||
Assert.Equal(expected, addrs.ToHashSet()); // exactly the valid set
|
||
Assert.DoesNotContain(0x48, addrs); // gap excluded
|
||
}
|
||
|
||
[Theory]
|
||
[InlineData(0x2F, "Upper Left MFD")]
|
||
[InlineData(0x20, "Upper Middle MFD")]
|
||
[InlineData(0x37, "Upper Right MFD")]
|
||
[InlineData(0x00, "Lower Right MFD")]
|
||
[InlineData(0x0F, "Lower Left MFD")]
|
||
[InlineData(0x38, "Throttle")]
|
||
[InlineData(0x10, "Secondary")]
|
||
[InlineData(0x18, "Screen")]
|
||
[InlineData(0x40, "Joystick")]
|
||
[InlineData(0x50, "Internal Keypad")]
|
||
[InlineData(0x6F, "External Keypad")]
|
||
public void Address_LandsInExpectedGroup(int address, string group)
|
||
{
|
||
PanelButton b = CockpitPanel.Buttons().Single(x => x.Address == address);
|
||
Assert.Equal(group, b.Group.Title);
|
||
}
|
||
|
||
[Fact]
|
||
public void Keypads_AreNotLampCapable()
|
||
{
|
||
foreach (PanelButton b in CockpitPanel.Buttons().Where(x => x.Group.Kind == PanelGroupKind.Keypad))
|
||
Assert.False(b.LampCapable);
|
||
// ...and everything else is.
|
||
foreach (PanelButton b in CockpitPanel.Buttons().Where(x => x.Group.Kind != PanelGroupKind.Keypad))
|
||
Assert.True(b.LampCapable);
|
||
}
|
||
|
||
[Fact]
|
||
public void Keypad_PhysicalLayout_MapsDigitsToAddresses()
|
||
{
|
||
// Internal keypad: top-left "1" -> 0x51, bottom-middle "0" -> 0x50, "C" -> 0x5C.
|
||
IList<PanelButton> all = CockpitPanel.Buttons();
|
||
PanelGroup pad = CockpitPanel.Groups.Single(g => g.Title == "Internal Keypad");
|
||
|
||
Assert.Equal(0x51, pad.Addresses[0]); // row0 col0 = "1"
|
||
Assert.Equal(0x5C, pad.Addresses[3]); // row0 col3 = "C"
|
||
Assert.Equal(0x50, pad.Addresses[13]); // row3 col1 = "0"
|
||
Assert.Equal(0x5F, pad.Addresses[15]); // row3 col3 = "F"
|
||
}
|
||
|
||
[Fact]
|
||
public void AllAddresses_AreValidRioAddresses()
|
||
{
|
||
foreach (PanelButton b in CockpitPanel.Buttons())
|
||
Assert.InRange(b.Address, 0, RioAddress.MaxAddress);
|
||
}
|
||
}
|