using System; using System.Collections.Generic; using Blacklight.Core.Keyboard; namespace Blacklight.Core.UnitTests.Keyboard { public class ScanCodesTests : UnitTestSharp.TestFixture { public static readonly (int, KeyCode)[] PlainKeys = { (0x01, KeyCode.Escape), (0x02, KeyCode.Digit1), (0x03, KeyCode.Digit2), (0x04, KeyCode.Digit3), (0x05, KeyCode.Digit4), (0x06, KeyCode.Digit5), (0x07, KeyCode.Digit6), (0x08, KeyCode.Digit7), (0x09, KeyCode.Digit8), (0x0A, KeyCode.Digit9), (0x0B, KeyCode.Digit0), (0x0C, KeyCode.Minus), (0x0D, KeyCode.Equal), (0x0E, KeyCode.Backspace), (0x0F, KeyCode.Tab), (0x10, KeyCode.Q), (0x11, KeyCode.W), (0x12, KeyCode.E), (0x13, KeyCode.R), (0x14, KeyCode.T), (0x15, KeyCode.Y), (0x16, KeyCode.U), (0x17, KeyCode.I), (0x18, KeyCode.O), (0x19, KeyCode.P), (0x1A, KeyCode.BracketLeft), (0x1B, KeyCode.BracketRight), (0x1C, KeyCode.MainEnter), (0x1D, KeyCode.ControlLeft), (0x1E, KeyCode.A), (0x1F, KeyCode.S), (0x20, KeyCode.D), (0x21, KeyCode.F), (0x22, KeyCode.G), (0x23, KeyCode.H), (0x24, KeyCode.J), (0x25, KeyCode.K), (0x26, KeyCode.L), (0x27, KeyCode.Semicolon), (0x28, KeyCode.Quote), (0x29, KeyCode.Backquote), (0x2A, KeyCode.ShiftLeft), (0x2B, KeyCode.Backslash), (0x2C, KeyCode.Z), (0x2D, KeyCode.X), (0x2E, KeyCode.C), (0x2F, KeyCode.V), (0x30, KeyCode.B), (0x31, KeyCode.N), (0x32, KeyCode.M), (0x33, KeyCode.Comma), (0x34, KeyCode.Period), (0x35, KeyCode.Slash), (0x36, KeyCode.ShiftRight), (0x37, KeyCode.NumpadMultiply), (0x38, KeyCode.AltLeft), (0x39, KeyCode.Space), (0x3A, KeyCode.CapsLock), (0x3B, KeyCode.F1), (0x3C, KeyCode.F2), (0x3D, KeyCode.F3), (0x3E, KeyCode.F4), (0x3F, KeyCode.F5), (0x40, KeyCode.F6), (0x41, KeyCode.F7), (0x42, KeyCode.F8), (0x43, KeyCode.F9), (0x44, KeyCode.F10), (0x45, KeyCode.NumLock), (0x46, KeyCode.ScrollLock), (0x47, KeyCode.Numpad7), (0x48, KeyCode.Numpad8), (0x49, KeyCode.Numpad9), (0x4A, KeyCode.NumpadSubtract), (0x4B, KeyCode.Numpad4), (0x4C, KeyCode.Numpad5), (0x4D, KeyCode.Numpad6), (0x4E, KeyCode.NumpadAdd), (0x4F, KeyCode.Numpad1), (0x50, KeyCode.Numpad2), (0x51, KeyCode.Numpad3), (0x52, KeyCode.Numpad0), (0x53, KeyCode.NumpadDecimal), (0x57, KeyCode.F11), (0x58, KeyCode.F12), }; public static readonly (int, KeyCode)[] ExtendedKeys = { (0x1C, KeyCode.NumpadEnter), (0x1D, KeyCode.ControlRight), (0x35, KeyCode.NumpadDivide), (0x38, KeyCode.AltRight), (0x45, KeyCode.NumLock), (0x47, KeyCode.Home), (0x48, KeyCode.ArrowUp), (0x49, KeyCode.PageUp), (0x4B, KeyCode.ArrowLeft), (0x4D, KeyCode.ArrowRight), (0x4F, KeyCode.End), (0x50, KeyCode.ArrowDown), (0x51, KeyCode.PageDown), (0x52, KeyCode.Insert), (0x53, KeyCode.Delete), (0x5D, KeyCode.ContextMenu), }; public class ToKeyCodeTests : UnitTestSharp.TestFixture { public void PlainScanCodes_MapToTheirPhysicalKey() { foreach (var (scanCode, expected) in PlainKeys) { CheckEqual(expected, ScanCodes.ToKeyCode(scanCode, extended: false).Value); } } public void ExtendedScanCodes_MapToTheirPhysicalKey() { foreach (var (scanCode, expected) in ExtendedKeys) { CheckEqual(expected, ScanCodes.ToKeyCode(scanCode, extended: true).Value); } } public void OneScanCodeCanBeADifferentKeyWhenExtended() { CheckEqual(KeyCode.ControlLeft, ScanCodes.ToKeyCode(0x1D, extended: false).Value); CheckEqual(KeyCode.ControlRight, ScanCodes.ToKeyCode(0x1D, extended: true).Value); CheckEqual(KeyCode.AltLeft, ScanCodes.ToKeyCode(0x38, extended: false).Value); CheckEqual(KeyCode.AltRight, ScanCodes.ToKeyCode(0x38, extended: true).Value); } public void KeysKeyCodeDoesNotModel_AreNull() { CheckNull(ScanCodes.ToKeyCode(0x00, extended: false)); CheckNull(ScanCodes.ToKeyCode(0x56, extended: false)); CheckNull(ScanCodes.ToKeyCode(0x59, extended: false)); CheckNull(ScanCodes.ToKeyCode(0x37, extended: true)); CheckNull(ScanCodes.ToKeyCode(0x5B, extended: true)); } public void FakeShiftWindowsSendsAroundNavigationKeys_IsNull() { CheckNull(ScanCodes.ToKeyCode(0x2A, extended: true)); CheckNull(ScanCodes.ToKeyCode(0x36, extended: true)); } public void EveryKeyCode_HasAScanCode() { var reached = new HashSet(); for (int scanCode = 0; scanCode < 0x100; scanCode++) { foreach (bool extended in new[] { false, true }) { KeyCode? keyCode = ScanCodes.ToKeyCode(scanCode, extended); if (keyCode.HasValue) { reached.Add(keyCode.Value); } } } foreach (KeyCode keyCode in Enum.GetValues(typeof(KeyCode))) { Check(reached.Contains(keyCode)); } } public void OnlyNumLock_HasTwoScanCodes() { var counts = new Dictionary(); for (int scanCode = 0; scanCode < 0x100; scanCode++) { foreach (bool extended in new[] { false, true }) { KeyCode? keyCode = ScanCodes.ToKeyCode(scanCode, extended); if (keyCode.HasValue) { int count; counts.TryGetValue(keyCode.Value, out count); counts[keyCode.Value] = count + 1; } } } foreach (var pair in counts) { CheckEqual(pair.Key == KeyCode.NumLock ? 2 : 1, pair.Value); } } } public class FromVirtualKeyTests : UnitTestSharp.TestFixture { public void Tab_IsTab() { CheckEqual(KeyCode.Tab, ScanCodes.FromVirtualKey(0x09).Value); } public void Return_IsMainEnter() { CheckEqual(KeyCode.MainEnter, ScanCodes.FromVirtualKey(0x0D).Value); } public void Escape_IsEscape() { CheckEqual(KeyCode.Escape, ScanCodes.FromVirtualKey(0x1B).Value); } public void FunctionKey_IsThatFunctionKey() { CheckEqual(KeyCode.F5, ScanCodes.FromVirtualKey(0x74).Value); } public void NavigationKeys_AreTheNavigationClusterNotTheKeypad() { (int, KeyCode)[] navigation = { (0x21, KeyCode.PageUp), (0x22, KeyCode.PageDown), (0x23, KeyCode.End), (0x24, KeyCode.Home), (0x25, KeyCode.ArrowLeft), (0x26, KeyCode.ArrowUp), (0x27, KeyCode.ArrowRight), (0x28, KeyCode.ArrowDown), (0x2D, KeyCode.Insert), (0x2E, KeyCode.Delete), }; foreach (var (virtualKey, expected) in navigation) { CheckEqual(expected, ScanCodes.FromVirtualKey(virtualKey).Value); } } public void GenericShift_IsTheLeftShift() { CheckEqual(KeyCode.ShiftLeft, ScanCodes.FromVirtualKey(0x10).Value); } public void RightHandModifiers_AreToldApart() { CheckEqual(KeyCode.ControlRight, ScanCodes.FromVirtualKey(0xA3).Value); CheckEqual(KeyCode.AltRight, ScanCodes.FromVirtualKey(0xA5).Value); CheckEqual(KeyCode.ShiftRight, ScanCodes.FromVirtualKey(0xA1).Value); } public void LockKeysAndContextMenu_MapToThemselves() { CheckEqual(KeyCode.NumLock, ScanCodes.FromVirtualKey(0x90).Value); CheckEqual(KeyCode.ScrollLock, ScanCodes.FromVirtualKey(0x91).Value); CheckEqual(KeyCode.ContextMenu, ScanCodes.FromVirtualKey(0x5D).Value); } public void NumpadKeys_MapToTheNumpadNotTheDigitRow() { (int, KeyCode)[] numpad = { (0x60, KeyCode.Numpad0), (0x61, KeyCode.Numpad1), (0x62, KeyCode.Numpad2), (0x63, KeyCode.Numpad3), (0x64, KeyCode.Numpad4), (0x65, KeyCode.Numpad5), (0x66, KeyCode.Numpad6), (0x67, KeyCode.Numpad7), (0x68, KeyCode.Numpad8), (0x69, KeyCode.Numpad9), (0x6A, KeyCode.NumpadMultiply), (0x6B, KeyCode.NumpadAdd), (0x6D, KeyCode.NumpadSubtract), (0x6E, KeyCode.NumpadDecimal), }; foreach (var (virtualKey, expected) in numpad) { CheckEqual(expected, ScanCodes.FromVirtualKey(virtualKey).Value); } } public void KeypadDivide_IsNumpadDivideNotSlash() { CheckEqual(KeyCode.NumpadDivide, ScanCodes.FromVirtualKey(0x6F).Value); } public void Pause_IsNull() { CheckNull(ScanCodes.FromVirtualKey(0x13)); } public void VirtualKeyWithNoKey_IsNull() { CheckNull(ScanCodes.FromVirtualKey(0xFF)); } } } }