Exemplo n.º 1
0
        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);
        }
Exemplo n.º 2
0
        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);
        }
Exemplo n.º 3
0
        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));
        }
Exemplo n.º 4
0
        /// <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);
        }
Exemplo n.º 5
0
        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();
            });
Exemplo n.º 6
0
 private static extern void SetHook([MarshalAs(UnmanagedType.FunctionPtr)] GlobalHook.CppGetMessageCallback callbackPointer, [MarshalAs(UnmanagedType.Bool)] bool blocking);
Exemplo n.º 7
0
 void IHookNativeMethods.SetHook(GlobalHook.CppGetMessageCallback callbackPointer, bool blocking) => SetHook(callbackPointer, blocking);
Exemplo n.º 8
0
        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);
        }
Exemplo n.º 9
0
        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);
        }