private GlobalHook.CppGetMessageCallback GetCallback() { GlobalHook.CppGetMessageCallback callback = null; hookNativeMethods.AllowMessageTypeRegistry(GlobalHook.MessageType.WM_CLIPBOARDUPDATE); hookNativeMethods.AllowMessageTypeRegistry(GlobalHook.MessageType.WM_PASTE); hookNativeMethods.AllowMessageTypeRegistry(GlobalHook.MessageType.WM_CUT); hookNativeMethods.AllowLibraryLoad(); var callbackReceivedEvent = new AutoResetEvent(false); hookNativeMethods.Mock .Setup( hook => hook.SetHook(It.IsAny <GlobalHook.CppGetMessageCallback>(), It.IsAny <bool>()))? .Callback((GlobalHook.CppGetMessageCallback cppCallback, bool isBlocking) => { callback = cppCallback; callbackReceivedEvent.Set(); }); //here the SetHook() method is called! clipboardModule.Initialize(true); clipboardPasteEventProducer.StartCapture(nativeClipboard.Mock.Object); //wait for the hookNativeMethodsMock.Mock.Callback is called! Assert.IsTrue(callbackReceivedEvent.WaitOne(MaxWaitTime), "Did not receive callback in time!"); callbackReceivedEvent.Dispose(); Assert.IsNotNull(callback, "Callback received however unexpectedly null!"); return(callback); }
private GlobalHook.CppGetMessageCallback GetCallback() { GlobalHook.CppGetMessageCallback callback = null; hookNativeMethods.AllowMessageTypeRegistry(GlobalHook.MessageType.WM_ENTERSIZEMOVE); hookNativeMethods.AllowMessageTypeRegistry(GlobalHook.MessageType.WM_EXITSIZEMOVE); hookNativeMethods.AllowLibraryLoad(); var callbackReceivedEvent = new AutoResetEvent(false); hookNativeMethods.Mock .Setup( hook => hook.SetHook(It.IsAny <GlobalHook.CppGetMessageCallback>(), It.IsAny <bool>()))? .Callback((GlobalHook.CppGetMessageCallback cppCallback, bool isBlocking) => { callback = cppCallback; callbackReceivedEvent.Set(); }); //here the SetHook() method is called! windowManagementModule.Initialize(true); windowResizingEventProducer.StartCapture(nativeWindowManagement.Mock.Object); windowMovementEventProducer.Close(); windowStateChangedEventProducer.Close(); ; //wait for the hookNativeMethodsMock.Mock.Callback is called! Assert.IsTrue(callbackReceivedEvent.WaitOne(MaxWaitTime), "Did not receive callback in time!"); callbackReceivedEvent.Dispose(); Assert.IsNotNull(callback, "Callback received however unexpectedly null!"); return(callback); }
public void TestGlobalHook_AddListener() { /* PRECONDITIONS */ Debug.Assert(hookNativeMethods != null); Debug.Assert(hookNativeMethods.Mock != null); /* GIVEN */ const int numOfEvent = 50; const int numOfNotEvent = 20; const GlobalHook.MessageType messageType = GlobalHook.MessageType.WM_USER; using var resetCounter = new CountdownEvent(numOfEvent); using var autoReset = new AutoResetEvent(false); GlobalHook.CppGetMessageCallback callback = null; hookNativeMethods.AllowMessageTypeRegistry(messageType); hookNativeMethods.AllowLibraryLoad(); hookNativeMethods.Mock .Setup(hook => hook.SetHook(It.IsAny <GlobalHook.CppGetMessageCallback>(), It.IsAny <bool>()))? .Callback((GlobalHook.CppGetMessageCallback cppCallback, bool isBlocking) => { callback = cppCallback; autoReset.Set(); }); /* WHEN */ GlobalHook.AddListener(message => { Assert.AreEqual((uint)messageType, message.Type); resetCounter.Signal(); }, messageType); GlobalHook.IsActive = true; Assert.IsTrue(autoReset.WaitOne(maxWaitTime)); Assert.IsNotNull(callback); for (var index = 0; index < numOfEvent; index++) { callback(new GlobalHook.HookMessage() { Type = (uint)messageType }); } // We check if our listener still gets called on events we don't care about. If it will this // test will throw because the resetCounter will be set to a negative number. for (var index = 0; index < numOfNotEvent; index++) { callback(new GlobalHook.HookMessage() { Type = (uint)GlobalHook.MessageType.WM_APP }); } /* THEN */ Assert.IsTrue(resetCounter.Wait(maxWaitTime)); }
/// <summary> /// Performs a series of initialization and Setups to get the CppGetMessageCallback. /// </summary> /// <returns>the callback that can be called with a message, which in turns calls a callback in the producers that is interested in this type of message</returns> private GlobalHook.CppGetMessageCallback GetCallback() { GlobalHook.CppGetMessageCallback callback = null; AllowMessageTypeRegistryForAll(); hookNativeMethodsMock.AllowLibraryLoad(); using var callbackReceivedEvent = new AutoResetEvent(false); hookNativeMethodsMock.Mock .Setup(hook => hook.SetHook(It.IsAny <GlobalHook.CppGetMessageCallback>(), It.IsAny <bool>()))? .Callback((GlobalHook.CppGetMessageCallback cppCallback, bool isBlocking) => { callback = cppCallback; callbackReceivedEvent.Set(); }); //here the SetHook() method is called! mouseModule.Initialize(true); mouseModule.IsActive = true; //wait for the hookNativeMethodsMock.Mock.Callback is called! Assert.IsTrue(callbackReceivedEvent.WaitOne(maxWaitTime), "Did not receive callback in time!"); Assert.IsNotNull(callback, "Callback received however unexpectedly null!"); return(callback); }
public void TestGlobalHook_RemoveListener() { /* PRECONDITIONS */ Debug.Assert(hookNativeMethods != null); Debug.Assert(hookNativeMethods.Mock != null); /* GIVEN */ const GlobalHook.MessageType messageType = GlobalHook.MessageType.WM_USER; using var autoReset = new AutoResetEvent(false); GlobalHook.CppGetMessageCallback callback = null; hookNativeMethods.AllowMessageTypeRegistry(messageType); hookNativeMethods.AllowLibraryLoad(); hookNativeMethods.Mock .Setup(hook => hook.SetHook(It.IsAny <GlobalHook.CppGetMessageCallback>(), It.IsAny <bool>()))? .Callback((GlobalHook.CppGetMessageCallback cppCallback, bool isBlocking) => { callback = cppCallback; autoReset.Set(); });
private static extern void SetHook([MarshalAs(UnmanagedType.FunctionPtr)] GlobalHook.CppGetMessageCallback callbackPointer, [MarshalAs(UnmanagedType.Bool)] bool blocking);
void IHookNativeMethods.SetHook(GlobalHook.CppGetMessageCallback callbackPointer, bool blocking) => SetHook(callbackPointer, blocking);
public void TestMouseScrollEventProducer_Callback() { /* PRECONDITIONS */ Debug.Assert(mouseModule != null); Debug.Assert(mouseScrollEventProducer != null); Debug.Assert(hookNativeMethodsMock != null); Debug.Assert(hookNativeMethodsMock.Mock != null); /* GIVEN */ //get the callback GlobalHook.CppGetMessageCallback callback = GetCallback(); //setting up fake nativeMouseMock behaviors, messages and corresponding expected Events GlobalHook.HookMessage[] hookMessages = { new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_MOUSEWHEEL, Hwnd = (IntPtr)1, wParam = (IntPtr)0x00780000, Data = new int[]{ 10, 100 } }, new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_MOUSEWHEEL, Hwnd = (IntPtr)2, wParam = (IntPtr)0x00080000, Data = new int[]{ 20, 200 } }, new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_MOUSEWHEEL, Hwnd = (IntPtr)23, wParam = (IntPtr)0xfff80000, Data = new int[]{ 54, 23 } }, new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_MOUSEWHEEL, Hwnd = (IntPtr)43, wParam = (IntPtr)0xff880000, Data = new int[]{ 33, 101 } } }; MouseScrollEvent[] expectedEvents = { new MouseScrollEvent { ScrollAmount = 120, HWnd = "1", MousePosition = new Point{ X = 10, Y = 100 } }, new MouseScrollEvent { ScrollAmount = 8, HWnd = "2", MousePosition = new Point{ X = 20, Y = 200 } }, new MouseScrollEvent { ScrollAmount = -8, HWnd = "23", MousePosition = new Point{ X = 54, Y = 23 } }, new MouseScrollEvent { ScrollAmount = -120, HWnd = "43", MousePosition = new Point{ X = 33, Y = 101 } } }; Assert.IsTrue(hookMessages.Length == expectedEvents.Length); /* WHEN */ // consumedEvent.Signal() will be called gdw one event has been found and meet expectation using var consumedEvent = new CountdownEvent(hookMessages.Length); Assert.IsTrue(consumedEvent.CurrentCount == hookMessages.Length); //didStartConsumingEvent.Set() will be called in Await method gdw the consumer is attached using var didStartConsumingEvent = new ManualResetEvent(false); //Running the task in another thread var thread = new Thread(async() => { await foreach (var @event in Await <IAsyncEnumerable <MouseScrollEvent> >(mouseScrollEventProducer.GetEvents(), didStartConsumingEvent)) { if (!IsMouseScrollEventFound(@event, expectedEvents)) { continue; } consumedEvent.Signal(); } }); thread.Start(); // true if the consumer is attached! Assert.IsTrue(didStartConsumingEvent.WaitOne(maxWaitTime)); // We must call the callback after the consumer is attached! // otherwise the message is automatically dismissed. foreach (GlobalHook.HookMessage message in hookMessages) { callback(message); } /* THEN */ //true if all events generated by the fake messages have meet expectation. Assert.IsTrue(consumedEvent.Wait(maxWaitTime), "Did not find all matching mouse scroll events in time."); //total shut down and resources release mouseModule.IsActive = false; mouseModule.Initialize(false); }
public void TestMouseClickEventProducer_Callback() { /* PRECONDITIONS */ Debug.Assert(mouseModule != null); Debug.Assert(mouseClickEventProducer != null); Debug.Assert(hookNativeMethodsMock != null); Debug.Assert(hookNativeMethodsMock.Mock != null); /* GIVEN */ //get the callback GlobalHook.CppGetMessageCallback callback = GetCallback(); //setting up fake nativeMouseMock behaviors, messages and corresponding expected Events GlobalHook.HookMessage[] hookMessages = { new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_RBUTTONDOWN, Hwnd = (IntPtr)1, Data = new int[]{ 1, 1 } }, new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_LBUTTONDOWN, Hwnd = (IntPtr)2, Data = new int[]{ 2, 2 } }, new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_MBUTTONDOWN, Hwnd = (IntPtr)3, Data = new int[]{ 3, 3 } }, new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_RBUTTONDBLCLK, Hwnd = (IntPtr)4, Data = new int[]{ 4, 4 } }, new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_LBUTTONDBLCLK, Hwnd = (IntPtr)5, Data = new int[]{ 5, 5 } }, new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_MBUTTONDBLCLK, Hwnd = (IntPtr)6, Data = new int[]{ 6, 6 } }, new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_NCRBUTTONDOWN, Hwnd = (IntPtr)7, Data = new int[]{ 7, 7 } }, new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_NCLBUTTONDOWN, Hwnd = (IntPtr)8, Data = new int[]{ 8, 8 } }, new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_NCMBUTTONDOWN, Hwnd = (IntPtr)9, Data = new int[]{ 9, 9 } }, new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_NCRBUTTONDBLCLK, Hwnd = (IntPtr)10, Data = new int[]{ 10, 10 } }, new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_NCLBUTTONDBLCLK, Hwnd = (IntPtr)11, Data = new int[]{ 11, 11 } }, new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_NCMBUTTONDBLCLK, Hwnd = (IntPtr)12, Data = new int[]{ 12, 12 } } }; MouseClickEvent[] expectedEvents = { new MouseClickEvent { MouseAction = MouseAction.RightClick, HWnd = "1", MousePosition = new Point{ X = 1, Y = 1 } }, new MouseClickEvent { MouseAction = MouseAction.LeftClick, HWnd = "2", MousePosition = new Point{ X = 2, Y = 2 } }, new MouseClickEvent { MouseAction = MouseAction.MiddleClick, HWnd = "3", MousePosition = new Point{ X = 3, Y = 3 } }, new MouseClickEvent { MouseAction = MouseAction.RightDoubleClick, HWnd = "4", MousePosition = new Point{ X = 4, Y = 4 } }, new MouseClickEvent { MouseAction = MouseAction.LeftDoubleClick, HWnd = "5", MousePosition = new Point{ X = 5, Y = 5 } }, new MouseClickEvent { MouseAction = MouseAction.MiddleDoubleClick, HWnd = "6", MousePosition = new Point{ X = 6, Y = 6 } }, new MouseClickEvent { MouseAction = MouseAction.RightClick, HWnd = "7", MousePosition = new Point{ X = 7, Y = 7 } }, new MouseClickEvent { MouseAction = MouseAction.LeftClick, HWnd = "8", MousePosition = new Point{ X = 8, Y = 8 } }, new MouseClickEvent { MouseAction = MouseAction.MiddleClick, HWnd = "9", MousePosition = new Point{ X = 9, Y = 9 } }, new MouseClickEvent { MouseAction = MouseAction.RightDoubleClick, HWnd = "10", MousePosition = new Point{ X = 10, Y = 10 } }, new MouseClickEvent { MouseAction = MouseAction.LeftDoubleClick, HWnd = "11", MousePosition = new Point{ X = 11, Y = 11 } }, new MouseClickEvent { MouseAction = MouseAction.MiddleDoubleClick, HWnd = "12", MousePosition = new Point{ X = 12, Y = 12 } } }; Assert.IsTrue(hookMessages.Length == expectedEvents.Length); /* WHEN */ // consumedEvent.Signal() will be called gdw one event has been found and meet expectation using var consumedEvent = new CountdownEvent(hookMessages.Length); Assert.IsTrue(consumedEvent.CurrentCount == hookMessages.Length); //didStartConsumingEvent.Set() will be called in Await method gdw the consumer is attached using var didStartConsumingEvent = new ManualResetEvent(false); //Running the task in another thread var thread = new Thread(async() => { await foreach (var @event in Await <IAsyncEnumerable <MouseClickEvent> >(mouseClickEventProducer.GetEvents(), didStartConsumingEvent)) { if (!IsMouseClickEventFound(@event, expectedEvents)) { continue; } consumedEvent.Signal(); } }); thread.Start(); // true if the consumer is attached! Assert.IsTrue(didStartConsumingEvent.WaitOne(maxWaitTime)); // We must call the callback after the consumer is attached! // otherwise the message is automatically dismissed. foreach (GlobalHook.HookMessage message in hookMessages) { callback(message); } /* THEN */ //true if all events generated by the fake messages have meet expectation. Assert.IsTrue(consumedEvent.Wait(maxWaitTime), "Did not find all matching mouse click events in time."); //total shut down and resources release mouseModule.IsActive = false; mouseModule.Initialize(false); }
public void TestKeyboardInteractEventProducer_ModifierKeysTest() { /* PRECONDITIONS */ Debug.Assert(keyboardModule != null); Debug.Assert(keyboardInteractEventProducer != null); Debug.Assert(hookNativeMethodsMock != null); Debug.Assert(hookNativeMethodsMock.Mock != null); Debug.Assert(nativeKeyboardMock != null); /* GIVEN */ //get the callback GlobalHook.CppGetMessageCallback callback = GetCallback(); //setting up fake nativeKeyboardMock behaviors, messages and corresponding expected Events nativeKeyboardMock.Setup(nativeK => nativeK.KeyFromVirtualKey(0x41)).Returns(Key.A); nativeKeyboardMock.Setup(nativeK => nativeK.KeyFromVirtualKey(0x42)).Returns(Key.B); nativeKeyboardMock.Setup(nativeK => nativeK.KeyFromVirtualKey(0x43)).Returns(Key.C); nativeKeyboardMock.Setup(nativeK => nativeK.KeyFromVirtualKey(0x44)).Returns(Key.D); nativeKeyboardMock.Setup(nativeK => nativeK.KeyFromVirtualKey(0x46)).Returns(Key.F); nativeKeyboardMock.Setup(nativeK => nativeK.KeyFromVirtualKey(0x47)).Returns(Key.G); nativeKeyboardMock.Setup(nativeK => nativeK.KeyFromVirtualKey(0x48)).Returns(Key.H); nativeKeyboardMock.Setup(nativeK => nativeK.KeyFromVirtualKey(0x49)).Returns(Key.I); nativeKeyboardMock.Setup(nativeK => nativeK.KeyFromVirtualKey(0x4A)).Returns(Key.J); // Setting up the modifierkeys sequence which should work together with the fake messages to generate expected events nativeKeyboardMock.SetupSequence(nM => nM.IsKeyPressed(INativeKeyboard.VirtualKeyCode.VK_MENU)) .Returns(true).Returns(false).Returns(false).Returns(false).Returns(false).Returns(true).Returns(true).Returns(false).Returns(true); nativeKeyboardMock.SetupSequence(nM => nM.IsKeyPressed(INativeKeyboard.VirtualKeyCode.VK_CONTROL)) .Returns(false).Returns(true).Returns(false).Returns(false).Returns(false).Returns(false).Returns(true).Returns(true).Returns(true); nativeKeyboardMock.SetupSequence(nM => nM.IsKeyPressed(INativeKeyboard.VirtualKeyCode.VK_SHIFT)) .Returns(false).Returns(false).Returns(true).Returns(false).Returns(false).Returns(true).Returns(false).Returns(true).Returns(true); nativeKeyboardMock.SetupSequence(nM => nM.IsKeyPressed(INativeKeyboard.VirtualKeyCode.VK_LWIN)) .Returns(false).Returns(false).Returns(false).Returns(true).Returns(false).Returns(false).Returns(false).Returns(false).Returns(false); nativeKeyboardMock.Setup(nM => nM.IsKeyPressed(INativeKeyboard.VirtualKeyCode.VK_RWIN)) .Returns(false); //setting up fake messages and corresponding expected Events GlobalHook.HookMessage[] hookMessages = { new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_KEYDOWN, wParam = (IntPtr)0x41 }, //A with Alt down new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_KEYDOWN, wParam = (IntPtr)0x42 }, //B with Control down new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_KEYDOWN, wParam = (IntPtr)0x43 }, //C with Shift down new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_KEYDOWN, wParam = (IntPtr)0x44 }, //D with Left Windows down new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_KEYDOWN, wParam = (IntPtr)0x46 }, //F with None new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_KEYDOWN, wParam = (IntPtr)0x47 }, //G with Alt + Shift down new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_KEYDOWN, wParam = (IntPtr)0x48 }, //H with Alt + Control down new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_KEYDOWN, wParam = (IntPtr)0x49 }, //I with Control + Shift down new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_KEYDOWN, wParam = (IntPtr)0x4A } //J with Control + Alt + Shift Windows down }; KeyboardInteractEvent[] expectedEvents = { new KeyboardInteractEvent { PressedKey_System_Windows_Input_Key = Key.A, ModifierKeys_System_Windows_Input_ModifierKeys = ModifierKeys.Alt }, new KeyboardInteractEvent { PressedKey_System_Windows_Input_Key = Key.B, ModifierKeys_System_Windows_Input_ModifierKeys = ModifierKeys.Control }, new KeyboardInteractEvent { PressedKey_System_Windows_Input_Key = Key.C, ModifierKeys_System_Windows_Input_ModifierKeys = ModifierKeys.Shift }, new KeyboardInteractEvent { PressedKey_System_Windows_Input_Key = Key.D, ModifierKeys_System_Windows_Input_ModifierKeys = ModifierKeys.Windows }, new KeyboardInteractEvent { PressedKey_System_Windows_Input_Key = Key.F, ModifierKeys_System_Windows_Input_ModifierKeys = ModifierKeys.None }, new KeyboardInteractEvent { PressedKey_System_Windows_Input_Key = Key.G, ModifierKeys_System_Windows_Input_ModifierKeys = ModifierKeys.Alt | ModifierKeys.Shift }, new KeyboardInteractEvent { PressedKey_System_Windows_Input_Key = Key.H, ModifierKeys_System_Windows_Input_ModifierKeys = ModifierKeys.Alt | ModifierKeys.Control }, new KeyboardInteractEvent { PressedKey_System_Windows_Input_Key = Key.I, ModifierKeys_System_Windows_Input_ModifierKeys = ModifierKeys.Shift | ModifierKeys.Control }, new KeyboardInteractEvent { PressedKey_System_Windows_Input_Key = Key.J, ModifierKeys_System_Windows_Input_ModifierKeys = ModifierKeys.Alt | ModifierKeys.Control | ModifierKeys.Shift } }; Assert.IsTrue(hookMessages.Length == expectedEvents.Length); /* WHEN */ // consumedEvent.Signal() will be called gdw one event has been found and meet expectation using var consumedEvent = new CountdownEvent(hookMessages.Length); Assert.IsTrue(consumedEvent.CurrentCount == hookMessages.Length); //didStartConsumingEvent.Set() will be called in Await method gdw the consumer is attached using var didStartConsumingEvent = new ManualResetEvent(false); //Running the task in another thread var thread = new Thread(async() => { await foreach (var @event in Await <IAsyncEnumerable <KeyboardInteractEvent> >(keyboardInteractEventProducer.GetEvents(), didStartConsumingEvent)) { if (!IsKeyboardInteractEventFound(@event, expectedEvents)) { continue; } consumedEvent.Signal(); } }); thread.Start(); // true if the consumer is attached! Assert.IsTrue(didStartConsumingEvent.WaitOne(maxWaitTime)); // We must call the callback after the consumer is attached! // otherwise the message is automatically dismissed. foreach (GlobalHook.HookMessage message in hookMessages) { callback(message); } /* THEN */ //true if all events generated by the fake messages have meet expectation. Assert.IsTrue(consumedEvent.Wait(maxWaitTime), "Did not find all matching keyboard interact events in time."); //total shut down and resources release keyboardInteractEventProducer.StopCapture(); keyboardModule.Initialize(false); }
public void TestKeyboardInteractEventProducer_PressedKeyTest() { /* PRECONDITIONS */ Debug.Assert(keyboardModule != null); Debug.Assert(keyboardInteractEventProducer != null); Debug.Assert(hookNativeMethodsMock != null); Debug.Assert(hookNativeMethodsMock.Mock != null); Debug.Assert(nativeKeyboardMock != null); /* GIVEN */ //get the callback GlobalHook.CppGetMessageCallback callback = GetCallback(); //setting up fake nativeKeyboardMock behaviors, messages and corresponding expected Events nativeKeyboardMock.Setup(nativeK => nativeK.KeyFromVirtualKey(0x41)).Returns(Key.A); nativeKeyboardMock.Setup(nativeK => nativeK.KeyFromVirtualKey(0x48)).Returns(Key.H); nativeKeyboardMock.Setup(nativeK => nativeK.KeyFromVirtualKey(0x36)).Returns(Key.D6); nativeKeyboardMock.Setup(nativeK => nativeK.KeyFromVirtualKey(0x30)).Returns(Key.D0); nativeKeyboardMock.Setup(nativeK => nativeK.KeyFromVirtualKey(0xBB)).Returns(Key.OemPlus); nativeKeyboardMock.Setup(nativeK => nativeK.KeyFromVirtualKey(0xBF)).Returns(Key.OemQuestion); nativeKeyboardMock.Setup(nativeK => nativeK.KeyFromVirtualKey(0xA0)).Returns(Key.LeftShift); nativeKeyboardMock.Setup(nativeK => nativeK.KeyFromVirtualKey(0x24)).Returns(Key.Home); nativeKeyboardMock.Setup(nativeK => nativeK.KeyFromVirtualKey(0x25)).Returns(Key.Left); nativeKeyboardMock.Setup(nativeK => nativeK.KeyFromVirtualKey(0x12)).Returns(Key.LeftAlt); GlobalHook.HookMessage[] hookMessages = { new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_KEYDOWN, wParam = (IntPtr)0x41 }, //A new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_SYSKEYDOWN, wParam = (IntPtr)0x48 }, //H new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_KEYDOWN, wParam = (IntPtr)0x36 }, //6 new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_KEYDOWN, wParam = (IntPtr)0x30 }, //0 new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_SYSKEYDOWN, wParam = (IntPtr)0xBB }, //+ new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_KEYDOWN, wParam = (IntPtr)0xBF }, //"/" or ? new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_SYSKEYDOWN, wParam = (IntPtr)0xA0 }, //Left SHIFT new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_SYSKEYDOWN, wParam = (IntPtr)0x24 }, //HOME new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_KEYDOWN, wParam = (IntPtr)0x25 }, //LeftArrow new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_KEYDOWN, wParam = (IntPtr)0x12 } //Alt }; KeyboardInteractEvent[] expectedEvents = { new KeyboardInteractEvent { PressedKey_System_Windows_Input_Key = Key.A }, new KeyboardInteractEvent { PressedKey_System_Windows_Input_Key = Key.H }, new KeyboardInteractEvent { PressedKey_System_Windows_Input_Key = Key.D6 }, new KeyboardInteractEvent { PressedKey_System_Windows_Input_Key = Key.D0 }, new KeyboardInteractEvent { PressedKey_System_Windows_Input_Key = Key.OemPlus }, new KeyboardInteractEvent { PressedKey_System_Windows_Input_Key = Key.OemQuestion }, new KeyboardInteractEvent { PressedKey_System_Windows_Input_Key = Key.LeftShift }, new KeyboardInteractEvent { PressedKey_System_Windows_Input_Key = Key.Home }, new KeyboardInteractEvent { PressedKey_System_Windows_Input_Key = Key.Left }, new KeyboardInteractEvent { PressedKey_System_Windows_Input_Key = Key.LeftAlt } }; Assert.IsTrue(hookMessages.Length == expectedEvents.Length); /* WHEN */ // consumedEvent.Signal() will be called gdw one event has been found and meet expectation using var consumedEvent = new CountdownEvent(hookMessages.Length); Assert.IsTrue(consumedEvent.CurrentCount == hookMessages.Length); //didStartConsumingEvent.Set() will be called in Await method gdw the consumer is attached using var didStartConsumingEvent = new ManualResetEvent(false); //Running the task in another thread var thread = new Thread(async() => { await foreach (var @event in Await <IAsyncEnumerable <KeyboardInteractEvent> >(keyboardInteractEventProducer.GetEvents(), didStartConsumingEvent)) { if (!IsKeyboardInteractEventFound(@event, expectedEvents)) { continue; } consumedEvent.Signal(); } }); thread.Start(); // true if the consumer is attached! Assert.IsTrue(didStartConsumingEvent.WaitOne(maxWaitTime)); // We must call the callback after the consumer is attached! // otherwise the message is automatically dismissed. foreach (GlobalHook.HookMessage message in hookMessages) { callback(message); } /* THEN */ //true if all events generated by the fake messages have meet expectation. Assert.IsTrue(consumedEvent.Wait(maxWaitTime), "Did not find all matching keyboard interact events in time."); //total shut down and resources release keyboardInteractEventProducer.StopCapture(); keyboardModule.Initialize(false); }
public void TestKeyboardInteractEventProducer_UnicodeTest() { /* PRECONDITIONS */ Debug.Assert(keyboardModule != null); Debug.Assert(keyboardInteractEventProducer != null); Debug.Assert(hookNativeMethodsMock != null); Debug.Assert(hookNativeMethodsMock.Mock != null); //setting up fake nativeKeyboardMock behaviors, messages and corresponding expected Events nativeKeyboardMock.Setup(nativeK => nativeK.KeyFromVirtualKey(0x41)).Returns(Key.A); nativeKeyboardMock.Setup(nativeK => nativeK.KeyFromVirtualKey(0x5A)).Returns(Key.Z); nativeKeyboardMock.Setup(nativeK => nativeK.KeyFromVirtualKey(0x30)).Returns(Key.D0); nativeKeyboardMock.Setup(nativeK => nativeK.KeyFromVirtualKey(0x39)).Returns(Key.D9); nativeKeyboardMock.Setup(nativeK => nativeK.KeyFromVirtualKey(0xBD)).Returns(Key.OemMinus); nativeKeyboardMock.Setup(nativeK => nativeK.KeyFromVirtualKey(0xBF)).Returns(Key.OemQuestion); nativeKeyboardMock.Setup(nativeK => nativeK.KeyFromVirtualKey(0x12)).Returns(Key.LeftAlt); nativeKeyboardMock.Setup(nativeK => nativeK.KeyFromVirtualKey(0xA2)).Returns(Key.LeftCtrl); nativeKeyboardMock.Setup(nativeK => nativeK.KeyFromVirtualKey(0x20)).Returns(Key.Space); nativeKeyboardMock.Setup(nativeK => nativeK.ToUnicode(0x41)).Returns('a'); nativeKeyboardMock.Setup(nativeK => nativeK.ToUnicode(0x5A)).Returns('z'); nativeKeyboardMock.Setup(nativeK => nativeK.ToUnicode(0x30)).Returns('0'); nativeKeyboardMock.Setup(nativeK => nativeK.ToUnicode(0x39)).Returns('9'); nativeKeyboardMock.Setup(nativeK => nativeK.ToUnicode(0xBD)).Returns('-'); nativeKeyboardMock.Setup(nativeK => nativeK.ToUnicode(0xBF)).Returns('/'); nativeKeyboardMock.Setup(nativeK => nativeK.ToUnicode(0x12)).Returns('\u0000'); nativeKeyboardMock.Setup(nativeK => nativeK.ToUnicode(0xA2)).Returns('\u0000'); nativeKeyboardMock.Setup(nativeK => nativeK.ToUnicode(0x20)).Returns(' '); /* GIVEN */ GlobalHook.CppGetMessageCallback callback = GetCallback(); //setting up fake messages and corresponding expected Events GlobalHook.HookMessage[] hookMessages = { new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_KEYDOWN, wParam = (IntPtr)0x41 }, //a new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_KEYDOWN, wParam = (IntPtr)0x5A }, //z new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_KEYDOWN, wParam = (IntPtr)0x30 }, //0 new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_KEYDOWN, wParam = (IntPtr)0x39 }, //9 new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_SYSKEYDOWN, wParam = (IntPtr)0xBD }, //- new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_KEYDOWN, wParam = (IntPtr)0xBF }, // '/' new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_KEYDOWN, wParam = (IntPtr)0x12 }, //alt new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_KEYDOWN, wParam = (IntPtr)0xA2 }, //control new GlobalHook.HookMessage { Type = (uint)GlobalHook.MessageType.WM_KEYDOWN, wParam = (IntPtr)0x20 } //space }; KeyboardInteractEvent[] expectedEvents = { new KeyboardInteractEvent { PressedKey_System_Windows_Input_Key = Key.A, MappedCharacter_Unicode = 'a' }, new KeyboardInteractEvent { PressedKey_System_Windows_Input_Key = Key.Z, MappedCharacter_Unicode = 'z' }, new KeyboardInteractEvent { PressedKey_System_Windows_Input_Key = Key.D0, MappedCharacter_Unicode = '0' }, new KeyboardInteractEvent { PressedKey_System_Windows_Input_Key = Key.D9, MappedCharacter_Unicode = '9' }, new KeyboardInteractEvent { PressedKey_System_Windows_Input_Key = Key.OemMinus, MappedCharacter_Unicode = '-' }, new KeyboardInteractEvent { PressedKey_System_Windows_Input_Key = Key.OemQuestion, MappedCharacter_Unicode = '/' }, new KeyboardInteractEvent { PressedKey_System_Windows_Input_Key = Key.LeftAlt, MappedCharacter_Unicode = '\u0000' }, new KeyboardInteractEvent { PressedKey_System_Windows_Input_Key = Key.LeftCtrl, MappedCharacter_Unicode = '\u0000' }, new KeyboardInteractEvent { PressedKey_System_Windows_Input_Key = Key.Space, MappedCharacter_Unicode = ' ' } }; Assert.IsTrue(hookMessages.Length == expectedEvents.Length); /* WHEN */ /* WHEN */ // consumedEvent.Signal() will be called gdw one event has been found and meet expectation using var consumedEvent = new CountdownEvent(hookMessages.Length); Assert.IsTrue(consumedEvent.CurrentCount == hookMessages.Length); //didStartConsumingEvent.Set() will be called in Await method gdw the consumer is attached using var didStartConsumingEvent = new ManualResetEvent(false); //Running the task in another thread var thread = new Thread(async() => { await foreach (var @event in Await <IAsyncEnumerable <KeyboardInteractEvent> >(keyboardInteractEventProducer.GetEvents(), didStartConsumingEvent)) { if (!IsKeyboardInteractEventFound(@event, expectedEvents)) { continue; } consumedEvent.Signal(); } }); thread.Start(); // true if the consumer is attached! Assert.IsTrue(didStartConsumingEvent.WaitOne(maxWaitTime)); // We must call the callback after the consumer is attached! // otherwise the message is automatically dismissed. foreach (GlobalHook.HookMessage message in hookMessages) { callback(message); } /* THEN */ Assert.IsTrue(consumedEvent.Wait(maxWaitTime), "Did not find all matching keyboard interact events in time."); //total shut down and resources release keyboardInteractEventProducer.StopCapture(); keyboardModule.Initialize(false); }