Fixes #4374 - Nukes all (?) legacy Driver and Application stuff; revamps tests (#4376)

This commit is contained in:
Tig
2025-11-11 16:29:33 -07:00
committed by GitHub
parent 559dea9239
commit d53fcd7485
310 changed files with 14827 additions and 16911 deletions

View File

@@ -0,0 +1,422 @@
namespace UnitTests_Parallelizable.DriverTests;
public class ConsoleKeyMappingTests
{
[Theory]
[InlineData ('a', ConsoleKey.A, false, false, false, (KeyCode)'a')]
[InlineData ('A', ConsoleKey.A, true, false, false, KeyCode.A | KeyCode.ShiftMask)]
[InlineData ('á', ConsoleKey.A, false, false, false, (KeyCode)'á')]
[InlineData ('Á', ConsoleKey.A, true, false, false, (KeyCode)'Á' | KeyCode.ShiftMask)]
[InlineData ('à', ConsoleKey.A, false, false, false, (KeyCode)'à')]
[InlineData ('À', ConsoleKey.A, true, false, false, (KeyCode)'À' | KeyCode.ShiftMask)]
[InlineData ('5', ConsoleKey.D5, false, false, false, KeyCode.D5)]
[InlineData ('%', ConsoleKey.D5, true, false, false, (KeyCode)'%' | KeyCode.ShiftMask)]
[InlineData ('€', ConsoleKey.D5, false, true, true, (KeyCode)'€' | KeyCode.AltMask | KeyCode.CtrlMask)]
[InlineData ('?', ConsoleKey.Oem4, true, false, false, (KeyCode)'?' | KeyCode.ShiftMask)]
[InlineData ('\'', ConsoleKey.Oem4, false, false, false, (KeyCode)'\'')]
[InlineData ('q', ConsoleKey.Q, false, false, false, (KeyCode)'q')]
[InlineData ('\0', ConsoleKey.F2, false, false, false, KeyCode.F2)]
[InlineData ('英', ConsoleKey.None, false, false, false, (KeyCode)'英')]
[InlineData ('\r', ConsoleKey.Enter, false, false, false, KeyCode.Enter)]
public void MapConsoleKeyInfoToKeyCode_Also_Return_Modifiers (
char keyChar,
ConsoleKey consoleKey,
bool shift,
bool alt,
bool control,
KeyCode expectedKeyCode
)
{
var consoleKeyInfo = new ConsoleKeyInfo (keyChar, consoleKey, shift, alt, control);
KeyCode keyCode = ConsoleKeyMapping.MapConsoleKeyInfoToKeyCode (consoleKeyInfo);
Assert.Equal (keyCode, expectedKeyCode);
}
[Theory]
[InlineData ('a', false, false, false, (KeyCode)'a')]
[InlineData ('A', true, false, false, KeyCode.A | KeyCode.ShiftMask)]
[InlineData ('á', false, false, false, (KeyCode)'á')]
[InlineData ('Á', true, false, false, (KeyCode)'Á' | KeyCode.ShiftMask)]
[InlineData ('à', false, false, false, (KeyCode)'à')]
[InlineData ('À', true, false, false, (KeyCode)'À' | KeyCode.ShiftMask)]
[InlineData ('5', false, false, false, KeyCode.D5)]
[InlineData ('%', true, false, false, (KeyCode)'%' | KeyCode.ShiftMask)]
[InlineData ('€', false, true, true, (KeyCode)'€' | KeyCode.AltMask | KeyCode.CtrlMask)]
[InlineData ('?', true, false, false, (KeyCode)'?' | KeyCode.ShiftMask)]
[InlineData ('\'', false, false, false, (KeyCode)'\'')]
[InlineData ('q', false, false, false, (KeyCode)'q')]
[InlineData ((uint)KeyCode.F2, false, false, false, KeyCode.F2)]
[InlineData ('英', false, false, false, (KeyCode)'英')]
[InlineData ('\r', false, false, false, KeyCode.Enter)]
[InlineData ('\n', false, false, false, (KeyCode)'\n')]
public void MapToKeyCodeModifiers_Tests (
uint keyChar,
bool shift,
bool alt,
bool control,
KeyCode expectedKeyCode
)
{
ConsoleModifiers modifiers = ConsoleKeyMapping.GetModifiers (shift, alt, control);
var keyCode = (KeyCode)keyChar;
keyCode = ConsoleKeyMapping.MapToKeyCodeModifiers (modifiers, keyCode);
Assert.Equal (keyCode, expectedKeyCode);
}
public static IEnumerable<object []> UnShiftedChars =>
new List<object []>
{
new object [] { 'a', 'A', KeyCode.A | KeyCode.ShiftMask },
new object [] { 'z', 'Z', KeyCode.Z | KeyCode.ShiftMask },
new object [] { 'á', 'Á', (KeyCode)'Á' | KeyCode.ShiftMask },
new object [] { 'à', 'À', (KeyCode)'À' | KeyCode.ShiftMask },
new object [] { 'ý', 'Ý', (KeyCode)'Ý' | KeyCode.ShiftMask },
new object [] { '1', '!', (KeyCode)'!' | KeyCode.ShiftMask },
new object [] { '2', '"', (KeyCode)'"' | KeyCode.ShiftMask },
new object [] { '3', '#', (KeyCode)'#' | KeyCode.ShiftMask },
new object [] { '4', '$', (KeyCode)'$' | KeyCode.ShiftMask },
new object [] { '5', '%', (KeyCode)'%' | KeyCode.ShiftMask },
new object [] { '6', '&', (KeyCode)'&' | KeyCode.ShiftMask },
new object [] { '7', '/', (KeyCode)'/' | KeyCode.ShiftMask },
new object [] { '8', '(', (KeyCode)'(' | KeyCode.ShiftMask },
new object [] { '9', ')', (KeyCode)')' | KeyCode.ShiftMask },
new object [] { '0', '=', (KeyCode)'=' | KeyCode.ShiftMask },
new object [] { '\\', '|', (KeyCode)'|' | KeyCode.ShiftMask },
new object [] { '\'', '?', (KeyCode)'?' | KeyCode.ShiftMask },
new object [] { '«', '»', (KeyCode)'»' | KeyCode.ShiftMask },
new object [] { '+', '*', (KeyCode)'*' | KeyCode.ShiftMask },
new object [] { '´', '`', (KeyCode)'`' | KeyCode.ShiftMask },
new object [] { 'º', 'ª', (KeyCode)'ª' | KeyCode.ShiftMask },
new object [] { '~', '^', (KeyCode)'^' | KeyCode.ShiftMask },
new object [] { '<', '>', (KeyCode)'>' | KeyCode.ShiftMask },
new object [] { ',', ';', (KeyCode)';' | KeyCode.ShiftMask },
new object [] { '.', ':', (KeyCode)':' | KeyCode.ShiftMask },
new object [] { '-', '_', (KeyCode)'_' | KeyCode.ShiftMask }
};
[Theory]
[InlineData (KeyCode.A, false, false, false)] // Unshifted A (lowercase)
[InlineData (KeyCode.B, false, false, false)]
[InlineData (KeyCode.Z, false, false, false)]
[InlineData (KeyCode.A | KeyCode.ShiftMask, true, false, false)] // Shifted A (uppercase)
[InlineData (KeyCode.Z | KeyCode.ShiftMask, true, false, false)]
[InlineData (KeyCode.A | KeyCode.CtrlMask, false, false, true)] // Ctrl+A
[InlineData (KeyCode.A | KeyCode.AltMask, false, true, false)] // Alt+A
[InlineData (KeyCode.A | KeyCode.ShiftMask | KeyCode.CtrlMask, true, false, true)] // Ctrl+Shift+A
[InlineData (KeyCode.A | KeyCode.ShiftMask | KeyCode.AltMask, true, true, false)] // Alt+Shift+A
[InlineData (KeyCode.A | KeyCode.CtrlMask | KeyCode.AltMask, false, true, true)] // Ctrl+Alt+A
[InlineData (KeyCode.A | KeyCode.ShiftMask | KeyCode.CtrlMask | KeyCode.AltMask, true, true, true)] // All modifiers
public void MapToConsoleModifiers_LetterKeys_ReturnsCorrectModifiers (
KeyCode key,
bool expectedShift,
bool expectedAlt,
bool expectedControl
)
{
// Act
ConsoleModifiers result = ConsoleKeyMapping.MapToConsoleModifiers (key);
// Assert
Assert.Equal (expectedShift, result.HasFlag (ConsoleModifiers.Shift));
Assert.Equal (expectedAlt, result.HasFlag (ConsoleModifiers.Alt));
Assert.Equal (expectedControl, result.HasFlag (ConsoleModifiers.Control));
}
[Theory]
[InlineData (KeyCode.A)] // 65 = 'A' in ASCII, but represents unshifted key
[InlineData (KeyCode.B)]
[InlineData (KeyCode.M)]
[InlineData (KeyCode.Z)]
public void MapToConsoleModifiers_UnshiftedLetterKeys_DoesNotSetShiftFlag (KeyCode key)
{
// This test verifies the BUGFIX: KeyCode.A-Z (65-90) represent UNSHIFTED keys,
// even though their numeric values match uppercase ASCII characters.
// The old code incorrectly checked char.IsUpper((char)key) which would fail this test.
// Act
ConsoleModifiers result = ConsoleKeyMapping.MapToConsoleModifiers (key);
// Assert - Shift should NOT be set for unshifted letter keys
Assert.False (result.HasFlag (ConsoleModifiers.Shift),
$"Shift should not be set for unshifted {key}. The KeyCode value {(int)key} represents a lowercase, unshifted key.");
}
[Theory]
[InlineData (KeyCode.D1, false)] // Unshifted number keys
[InlineData (KeyCode.D5, false)]
[InlineData (KeyCode.Space, false)]
[InlineData (KeyCode.Enter, false)]
[InlineData (KeyCode.Tab, false)]
[InlineData (KeyCode.D1 | KeyCode.ShiftMask, true)] // Shifted number keys
public void MapToConsoleModifiers_NonLetterKeys_ReturnsCorrectShiftState (KeyCode key, bool expectedShift)
{
// Act
ConsoleModifiers result = ConsoleKeyMapping.MapToConsoleModifiers (key);
// Assert
Assert.Equal (expectedShift, result.HasFlag (ConsoleModifiers.Shift));
}
[Theory]
[InlineData (KeyCode.A, 'a', ConsoleKey.A, false)] // Unshifted A = lowercase 'a'
[InlineData (KeyCode.B, 'b', ConsoleKey.B, false)]
[InlineData (KeyCode.M, 'm', ConsoleKey.M, false)]
[InlineData (KeyCode.Z, 'z', ConsoleKey.Z, false)]
public void GetConsoleKeyInfoFromKeyCode_UnshiftedLetterKeys_ReturnsLowercaseChar (
KeyCode key,
char expectedChar,
ConsoleKey expectedKey,
bool expectedShift
)
{
// This test verifies the BUGFIX: Key.A through Key.Z should produce lowercase characters
// when no ShiftMask is set. The old code would incorrectly return uppercase 'A'.
// Act
ConsoleKeyInfo result = ConsoleKeyMapping.GetConsoleKeyInfoFromKeyCode (key);
// Assert
Assert.Equal (expectedChar, result.KeyChar);
Assert.Equal (expectedKey, result.Key);
Assert.Equal (expectedShift, (result.Modifiers & ConsoleModifiers.Shift) != 0);
}
[Theory]
[InlineData (KeyCode.A | KeyCode.ShiftMask, 'A', ConsoleKey.A, true)] // Shifted A = uppercase 'A'
[InlineData (KeyCode.B | KeyCode.ShiftMask, 'B', ConsoleKey.B, true)]
[InlineData (KeyCode.M | KeyCode.ShiftMask, 'M', ConsoleKey.M, true)]
[InlineData (KeyCode.Z | KeyCode.ShiftMask, 'Z', ConsoleKey.Z, true)]
public void GetConsoleKeyInfoFromKeyCode_ShiftedLetterKeys_ReturnsUppercaseChar (
KeyCode key,
char expectedChar,
ConsoleKey expectedKey,
bool expectedShift
)
{
// Act
ConsoleKeyInfo result = ConsoleKeyMapping.GetConsoleKeyInfoFromKeyCode (key);
// Assert
Assert.Equal (expectedChar, result.KeyChar);
Assert.Equal (expectedKey, result.Key);
Assert.Equal (expectedShift, (result.Modifiers & ConsoleModifiers.Shift) != 0);
}
[Theory]
[InlineData (KeyCode.A | KeyCode.CtrlMask, ConsoleKey.A, false, false, true)]
[InlineData (KeyCode.A | KeyCode.AltMask, ConsoleKey.A, false, true, false)]
[InlineData (KeyCode.A | KeyCode.ShiftMask | KeyCode.CtrlMask, ConsoleKey.A, true, false, true)]
[InlineData (KeyCode.Z | KeyCode.CtrlMask, ConsoleKey.Z, false, false, true)]
public void GetConsoleKeyInfoFromKeyCode_LetterKeysWithModifiers_ReturnsCorrectModifiers (
KeyCode key,
ConsoleKey expectedConsoleKey,
bool expectedShift,
bool expectedAlt,
bool expectedControl
)
{
// Act
ConsoleKeyInfo result = ConsoleKeyMapping.GetConsoleKeyInfoFromKeyCode (key);
// Assert
Assert.Equal (expectedConsoleKey, result.Key);
Assert.Equal (expectedShift, (result.Modifiers & ConsoleModifiers.Shift) != 0);
Assert.Equal (expectedAlt, (result.Modifiers & ConsoleModifiers.Alt) != 0);
Assert.Equal (expectedControl, (result.Modifiers & ConsoleModifiers.Control) != 0);
}
[Theory]
[InlineData (KeyCode.Enter, '\r', ConsoleKey.Enter)]
[InlineData (KeyCode.Tab, '\t', ConsoleKey.Tab)]
[InlineData (KeyCode.Esc, '\u001B', ConsoleKey.Escape)]
[InlineData (KeyCode.Backspace, '\b', ConsoleKey.Backspace)]
[InlineData (KeyCode.Space, ' ', ConsoleKey.Spacebar)]
public void GetConsoleKeyInfoFromKeyCode_SpecialKeys_ReturnsCorrectKeyChar (
KeyCode key,
char expectedChar,
ConsoleKey expectedKey
)
{
// Act
ConsoleKeyInfo result = ConsoleKeyMapping.GetConsoleKeyInfoFromKeyCode (key);
// Assert
Assert.Equal (expectedChar, result.KeyChar);
Assert.Equal (expectedKey, result.Key);
}
[Theory]
[InlineData (KeyCode.F1, ConsoleKey.F1)]
[InlineData (KeyCode.F5, ConsoleKey.F5)]
[InlineData (KeyCode.F12, ConsoleKey.F12)]
[InlineData (KeyCode.CursorUp, ConsoleKey.UpArrow)]
[InlineData (KeyCode.CursorDown, ConsoleKey.DownArrow)]
[InlineData (KeyCode.CursorLeft, ConsoleKey.LeftArrow)]
[InlineData (KeyCode.CursorRight, ConsoleKey.RightArrow)]
[InlineData (KeyCode.Home, ConsoleKey.Home)]
[InlineData (KeyCode.End, ConsoleKey.End)]
[InlineData (KeyCode.PageUp, ConsoleKey.PageUp)]
[InlineData (KeyCode.PageDown, ConsoleKey.PageDown)]
[InlineData (KeyCode.Delete, ConsoleKey.Delete)]
[InlineData (KeyCode.Insert, ConsoleKey.Insert)]
public void GetConsoleKeyInfoFromKeyCode_NavigationAndFunctionKeys_ReturnsCorrectConsoleKey (
KeyCode key,
ConsoleKey expectedKey
)
{
// Act
ConsoleKeyInfo result = ConsoleKeyMapping.GetConsoleKeyInfoFromKeyCode (key);
// Assert
Assert.Equal (expectedKey, result.Key);
}
[Theory]
[InlineData (KeyCode.D0, '0', ConsoleKey.D0)]
[InlineData (KeyCode.D1, '1', ConsoleKey.D1)]
[InlineData (KeyCode.D5, '5', ConsoleKey.D5)]
[InlineData (KeyCode.D9, '9', ConsoleKey.D9)]
public void GetConsoleKeyInfoFromKeyCode_NumberKeys_ReturnsCorrectKeyChar (
KeyCode key,
char expectedChar,
ConsoleKey expectedKey
)
{
// Act
ConsoleKeyInfo result = ConsoleKeyMapping.GetConsoleKeyInfoFromKeyCode (key);
// Assert
Assert.Equal (expectedChar, result.KeyChar);
Assert.Equal (expectedKey, result.Key);
}
[Fact]
public void MapToConsoleModifiers_AllLetterKeys_UnshiftedDoesNotSetShift ()
{
// This comprehensive test ensures ALL letter keys A-Z without ShiftMask
// do not have Shift set in the returned modifiers.
// This will fail if the old "char.IsUpper" check is present.
for (KeyCode key = KeyCode.A; key <= KeyCode.Z; key++)
{
// Act
ConsoleModifiers result = ConsoleKeyMapping.MapToConsoleModifiers (key);
// Assert
Assert.False (
result.HasFlag (ConsoleModifiers.Shift),
$"Shift should not be set for unshifted {key} (value {(int)key}). " +
$"KeyCode.{key} represents a lowercase, unshifted key even though its numeric value is {(int)key}."
);
}
}
[Fact]
public void MapToConsoleModifiers_AllLetterKeysShifted_SetsShift ()
{
// Verify that WITH ShiftMask, all letter keys DO set Shift
for (KeyCode key = KeyCode.A; key <= KeyCode.Z; key++)
{
KeyCode shiftedKey = key | KeyCode.ShiftMask;
// Act
ConsoleModifiers result = ConsoleKeyMapping.MapToConsoleModifiers (shiftedKey);
// Assert
Assert.True (
result.HasFlag (ConsoleModifiers.Shift),
$"Shift should be set for {shiftedKey}"
);
}
}
[Fact]
public void GetConsoleKeyInfoFromKeyCode_AllUnshiftedLetterKeys_ReturnLowercaseChars ()
{
// This comprehensive test verifies ALL letter keys A-Z produce lowercase characters
// when no ShiftMask is set. This is the KEY test that will fail with the old code.
for (KeyCode key = KeyCode.A; key <= KeyCode.Z; key++)
{
// Act
ConsoleKeyInfo result = ConsoleKeyMapping.GetConsoleKeyInfoFromKeyCode (key);
// Calculate expected lowercase character
char expectedChar = (char)('a' + (key - KeyCode.A));
// Assert
Assert.True (
char.IsLower (result.KeyChar),
$"KeyChar for unshifted {key} should be lowercase, but got '{result.KeyChar}' (0x{(int)result.KeyChar:X2}). " +
$"Expected lowercase '{expectedChar}' (0x{(int)expectedChar:X2})."
);
Assert.Equal (
expectedChar,
result.KeyChar
);
Assert.False (
(result.Modifiers & ConsoleModifiers.Shift) != 0,
$"Shift modifier should not be set for unshifted {key}"
);
}
}
[Fact]
public void GetConsoleKeyInfoFromKeyCode_AllShiftedLetterKeys_ReturnUppercaseChars ()
{
// Verify that WITH ShiftMask, all letter keys produce uppercase characters
for (KeyCode key = KeyCode.A; key <= KeyCode.Z; key++)
{
KeyCode shiftedKey = key | KeyCode.ShiftMask;
// Act
ConsoleKeyInfo result = ConsoleKeyMapping.GetConsoleKeyInfoFromKeyCode (shiftedKey);
// Calculate expected uppercase character
char expectedChar = (char)('A' + (key - KeyCode.A));
// Assert
Assert.True (
char.IsUpper (result.KeyChar),
$"KeyChar for shifted {shiftedKey} should be uppercase, but got '{result.KeyChar}'"
);
Assert.Equal (expectedChar, result.KeyChar);
Assert.True (
(result.Modifiers & ConsoleModifiers.Shift) != 0,
$"Shift modifier should be set for {shiftedKey}"
);
}
}
[Theory]
[InlineData (KeyCode.A, KeyCode.A | KeyCode.ShiftMask, 'a', 'A')] // Without vs With Shift
[InlineData (KeyCode.M, KeyCode.M | KeyCode.ShiftMask, 'm', 'M')]
[InlineData (KeyCode.Z, KeyCode.Z | KeyCode.ShiftMask, 'z', 'Z')]
public void GetConsoleKeyInfoFromKeyCode_ShiftMaskChangesCase (
KeyCode unshifted,
KeyCode shifted,
char expectedUnshiftedChar,
char expectedShiftedChar
)
{
// Act
ConsoleKeyInfo unshiftedResult = ConsoleKeyMapping.GetConsoleKeyInfoFromKeyCode (unshifted);
ConsoleKeyInfo shiftedResult = ConsoleKeyMapping.GetConsoleKeyInfoFromKeyCode (shifted);
// Assert - Unshifted should be lowercase
Assert.Equal (expectedUnshiftedChar, unshiftedResult.KeyChar);
Assert.False ((unshiftedResult.Modifiers & ConsoleModifiers.Shift) != 0);
// Assert - Shifted should be uppercase
Assert.Equal (expectedShiftedChar, shiftedResult.KeyChar);
Assert.True ((shiftedResult.Modifiers & ConsoleModifiers.Shift) != 0);
}
}