private static void BufferVerificationHelper(CmdApp app, ViewportArea area, IntPtr hConsole, GetExpectedChar expectedCharAlgorithm)
        {
            WinCon.SMALL_RECT    viewport    = app.GetViewport(hConsole);
            Rectangle            selectRect  = new Rectangle(viewport.Left, viewport.Top, viewport.Width, viewport.Height);
            IEnumerable <string> scrapedText = area.GetLinesInRectangle(hConsole, selectRect);

            Verify.AreEqual(viewport.Height, scrapedText.Count(), "Verify the rows scraped is equal to the entire viewport height.");

            bool isValidState = true;

            string[] rows = scrapedText.ToArray();
            for (int i = 0; i < rows.Length; i++)
            {
                for (int j = 0; j < viewport.Width; j++)
                {
                    char actual   = rows[i][j];
                    char expected = expectedCharAlgorithm(i, j, rows.Length, viewport.Width);

                    isValidState = actual == expected;

                    if (!isValidState)
                    {
                        Verify.Fail(string.Format("Text buffer verification failed at Row: {0} Col: {1} Expected: '{2}' Actual: '{3}'", i, j, expected, actual));
                        break;
                    }
                }

                if (!isValidState)
                {
                    break;
                }
            }
        }
Esempio n. 2
0
        // Adapted from .NET source code...
        // See: http://referencesource.microsoft.com/#mscorlib/system/console.cs,fcb364a853d81c57
        private static void SetWindowPosition(int left, int top)
        {
            AutoHelpers.LogInvariant("Attempt to set console viewport buffer to Left: {0} and Top: {1}", left, top);

            IntPtr hConsole = WinCon.GetStdHandle(WinCon.CONSOLE_STD_HANDLE.STD_OUTPUT_HANDLE);

            // Get the size of the current console window
            WinCon.CONSOLE_SCREEN_BUFFER_INFO csbi = new WinCon.CONSOLE_SCREEN_BUFFER_INFO();
            NativeMethods.Win32BoolHelper(WinCon.GetConsoleScreenBufferInfo(hConsole, out csbi), "Get console screen buffer for viewport size information.");

            WinCon.SMALL_RECT srWindow = csbi.srWindow;
            AutoHelpers.LogInvariant("Initial viewport position: {0}", srWindow);

            // Check for arithmetic underflows & overflows.
            int newRight = left + srWindow.Right - srWindow.Left + 1;

            if (left < 0 || newRight > csbi.dwSize.X || newRight < 0)
            {
                throw new ArgumentOutOfRangeException("left");
            }
            int newBottom = top + srWindow.Bottom - srWindow.Top + 1;

            if (top < 0 || newBottom > csbi.dwSize.Y || newBottom < 0)
            {
                throw new ArgumentOutOfRangeException("top");
            }

            // Preserve the size, but move the position.
            srWindow.Bottom -= (short)(srWindow.Top - top);
            srWindow.Right  -= (short)(srWindow.Left - left);
            srWindow.Left    = (short)left;
            srWindow.Top     = (short)top;

            NativeMethods.Win32BoolHelper(WinCon.SetConsoleWindowInfo(hConsole, true, ref srWindow), string.Format("Attempt to update viewport position to {0}.", srWindow));
        }
        private static void TestInsertDelete(CmdApp app, ViewportArea area, IntPtr hConsole)
        {
            Log.Comment("--Insert/Delete Commands");
            ScreenFillHelper(app, area, hConsole);

            Log.Comment("Move cursor to the middle-ish");
            Point cursorExpected = new Point();

            // H is at 5, 1. VT coords are 1-based and buffer is 0-based so adjust.
            cursorExpected.Y = 5 - 1;
            cursorExpected.X = 1 - 1;
            app.UIRoot.SendKeys("H");

            // Move to middle-ish from here. 10 Bs and 10 Cs should about do it.
            for (int i = 0; i < 10; i++)
            {
                app.UIRoot.SendKeys("BC");
                cursorExpected.Y++;
                cursorExpected.X++;
            }

            WinCon.SMALL_RECT viewport = app.GetViewport(hConsole);

            // The entire buffer should be Zs except for what we're about to insert and delete.
            app.UIRoot.SendKeys("O"); // insert
            WinCon.CHAR_INFO ciCursor = area.GetCharInfoAt(hConsole, cursorExpected);
            Verify.AreEqual(' ', ciCursor.UnicodeChar);

            Point endOfCursorLine = new Point(viewport.Right, cursorExpected.Y);

            app.UIRoot.SendKeys("P"); // delete
            WinCon.CHAR_INFO ciEndOfLine = area.GetCharInfoAt(hConsole, endOfCursorLine);
            Verify.AreEqual(' ', ciEndOfLine.UnicodeChar);
            ciCursor = area.GetCharInfoAt(hConsole, cursorExpected);
            Verify.AreEqual('Z', ciCursor.UnicodeChar);

            // Move to end of line and check both insert and delete operations
            while (cursorExpected.X < viewport.Right)
            {
                app.UIRoot.SendKeys("C");
                cursorExpected.X++;
            }

            // move up a line to get some fresh Z
            app.UIRoot.SendKeys("A");
            cursorExpected.Y--;

            app.UIRoot.SendKeys("O"); // insert at end of line
            ciCursor = area.GetCharInfoAt(hConsole, cursorExpected);
            Verify.AreEqual(' ', ciCursor.UnicodeChar);

            // move up a line to get some fresh Z
            app.UIRoot.SendKeys("A");
            cursorExpected.Y--;

            app.UIRoot.SendKeys("P"); // delete at end of line
            ciCursor = area.GetCharInfoAt(hConsole, cursorExpected);
            Verify.AreEqual(' ', ciCursor.UnicodeChar);
        }
        public WinCon.CHAR_INFO[,] GetCharInfoInRectangle(IntPtr handle, Rectangle rect)
        {
            WinCon.SMALL_RECT readRectangle = new WinCon.SMALL_RECT();
            readRectangle.Top    = (short)rect.Top;
            readRectangle.Bottom = (short)(rect.Bottom - 1);
            readRectangle.Left   = (short)rect.Left;
            readRectangle.Right  = (short)(rect.Right - 1);

            WinCon.COORD dataBufferSize = new WinCon.COORD();
            dataBufferSize.X = (short)rect.Width;
            dataBufferSize.Y = (short)rect.Height;

            WinCon.COORD dataBufferPos = new WinCon.COORD();
            dataBufferPos.X = 0;
            dataBufferPos.Y = 0;

            WinCon.CHAR_INFO[,] data = new WinCon.CHAR_INFO[dataBufferSize.Y, dataBufferSize.X];

            NativeMethods.Win32BoolHelper(WinCon.ReadConsoleOutput(handle, data, dataBufferSize, dataBufferPos, ref readRectangle), string.Format("Attempting to read rectangle (L: {0}, T: {1}, R: {2}, B: {3}) from output buffer.", readRectangle.Left, readRectangle.Top, readRectangle.Right, readRectangle.Bottom));

            return(data);
        }
Esempio n. 5
0
        public void TestMouseSelection()
        {
            using (CmdApp app = new CmdApp(CreateType.ProcessOnly, TestContext))
            {
                using (ViewportArea area = new ViewportArea(app))
                {
                    // Set up the area we're going to attempt to select
                    Point startPoint = new Point();
                    Point endPoint   = new Point();

                    startPoint.X = 1;
                    startPoint.Y = 2;

                    endPoint.X = 10;
                    endPoint.Y = 10;

                    // Save expected anchor
                    WinCon.COORD expectedAnchor = new WinCon.COORD();
                    expectedAnchor.X = (short)startPoint.X;
                    expectedAnchor.Y = (short)startPoint.Y;

                    // Also save bottom right corner for the end of the selection
                    WinCon.COORD expectedBottomRight = new WinCon.COORD();
                    expectedBottomRight.X = (short)endPoint.X;
                    expectedBottomRight.Y = (short)endPoint.Y;

                    // Prepare the mouse by moving it into the start position. Prepare the structure
                    WinCon.CONSOLE_SELECTION_INFO csi;
                    WinCon.SMALL_RECT             expectedRect = new WinCon.SMALL_RECT();

                    WinCon.CONSOLE_SELECTION_INFO_FLAGS flagsExpected = WinCon.CONSOLE_SELECTION_INFO_FLAGS.CONSOLE_NO_SELECTION;

                    // 1. Place mouse button down to start selection and check state
                    area.MouseMove(startPoint);
                    area.MouseDown();

                    Globals.WaitForTimeout();                                                           // must wait after mouse operation. No good waiters since we have no UI objects

                    flagsExpected |= WinCon.CONSOLE_SELECTION_INFO_FLAGS.CONSOLE_SELECTION_IN_PROGRESS; // a selection is occurring
                    flagsExpected |= WinCon.CONSOLE_SELECTION_INFO_FLAGS.CONSOLE_MOUSE_SELECTION;       // it's a "Select" mode not "Mark" mode selection
                    flagsExpected |= WinCon.CONSOLE_SELECTION_INFO_FLAGS.CONSOLE_MOUSE_DOWN;            // the mouse is still down
                    flagsExpected |= WinCon.CONSOLE_SELECTION_INFO_FLAGS.CONSOLE_SELECTION_NOT_EMPTY;   // mouse selections are never empty. minimum 1x1

                    expectedRect.Top    = expectedAnchor.Y;                                             // rectangle is just at the point itself 1x1 size
                    expectedRect.Left   = expectedAnchor.X;
                    expectedRect.Bottom = expectedRect.Top;
                    expectedRect.Right  = expectedRect.Left;

                    NativeMethods.Win32BoolHelper(WinCon.GetConsoleSelectionInfo(out csi), "Check state on mouse button down to start selection.");
                    Log.Comment("Selection Info: {0}", csi);

                    Verify.AreEqual(csi.Flags, flagsExpected, "Check initial mouse selection with button still down.");
                    Verify.AreEqual(csi.SelectionAnchor, expectedAnchor, "Check that the anchor is equal to the start point.");
                    Verify.AreEqual(csi.Selection, expectedRect, "Check that entire rectangle is the size of 1x1 and is just at the anchor point.");

                    // 2. Move to end point and release cursor
                    area.MouseMove(endPoint);
                    area.MouseUp();

                    Globals.WaitForTimeout(); // must wait after mouse operation. No good waiters since we have no UI objects

                    // on button up, remove mouse down flag
                    flagsExpected &= ~WinCon.CONSOLE_SELECTION_INFO_FLAGS.CONSOLE_MOUSE_DOWN;

                    // anchor remains the same
                    // bottom right of rectangle now changes to the end point
                    expectedRect.Bottom = expectedBottomRight.Y;
                    expectedRect.Right  = expectedBottomRight.X;

                    NativeMethods.Win32BoolHelper(WinCon.GetConsoleSelectionInfo(out csi), "Check state after drag and release mouse.");
                    Log.Comment("Selection Info: {0}", csi);

                    Verify.AreEqual(csi.Flags, flagsExpected, "Check selection is still on and valid, but button is up.");
                    Verify.AreEqual(csi.SelectionAnchor, expectedAnchor, "Check that the anchor is still equal to the start point.");
                    Verify.AreEqual(csi.Selection, expectedRect, "Check that entire rectangle reaches from start to end point.");

                    // 3. Leave mouse selection
                    area.ExitModes();

                    flagsExpected = WinCon.CONSOLE_SELECTION_INFO_FLAGS.CONSOLE_NO_SELECTION;

                    NativeMethods.Win32BoolHelper(WinCon.GetConsoleSelectionInfo(out csi), "Check state after exiting mouse selection.");
                    Log.Comment("Selection Info: {0}", csi);

                    Verify.AreEqual(csi.Flags, flagsExpected, "Check that selection state is reset.");
                }
            }
        }
Esempio n. 6
0
        public void TestKeyboardSelection()
        {
            using (RegistryHelper reg = new RegistryHelper())
            {
                reg.BackupRegistry();

                VersionSelector.SetConsoleVersion(reg, ConsoleVersion.V2);

                using (CmdApp app = new CmdApp(CreateType.ProcessOnly, TestContext))
                {
                    using (ViewportArea area = new ViewportArea(app))
                    {
                        WinCon.CONSOLE_SELECTION_INFO csi;
                        NativeMethods.Win32BoolHelper(WinCon.GetConsoleSelectionInfo(out csi), "Get initial selection state.");
                        Log.Comment("Selection Info: {0}", csi);

                        Verify.AreEqual(csi.Flags, WinCon.CONSOLE_SELECTION_INFO_FLAGS.CONSOLE_NO_SELECTION, "Confirm no selection in progress.");
                        // ignore rectangle and coords. They're undefined when there is no selection.

                        // Get cursor position at the beginning of this operation. The anchor will start at the cursor position for v2 console.
                        // NOTE: It moved to 0,0 for the v1 console.
                        IntPtr hConsole = WinCon.GetStdHandle(WinCon.CONSOLE_STD_HANDLE.STD_OUTPUT_HANDLE);
                        Verify.IsNotNull(hConsole, "Ensure the STDOUT handle is valid.");

                        WinCon.CONSOLE_SCREEN_BUFFER_INFO_EX cbiex = new WinCon.CONSOLE_SCREEN_BUFFER_INFO_EX();
                        cbiex.cbSize = (uint)Marshal.SizeOf(cbiex);
                        NativeMethods.Win32BoolHelper(WinCon.GetConsoleScreenBufferInfoEx(hConsole, ref cbiex), "Get initial cursor position (from screen buffer info)");

                        // The expected anchor when we're done is this initial cursor position
                        WinCon.COORD expectedAnchor = new WinCon.COORD();
                        expectedAnchor.X = cbiex.dwCursorPosition.X;
                        expectedAnchor.Y = cbiex.dwCursorPosition.Y;

                        // The expected rect is going to start from this cursor position. We'll modify it after we perform some operations.
                        WinCon.SMALL_RECT expectedRect = new WinCon.SMALL_RECT();
                        expectedRect.Top    = expectedAnchor.Y;
                        expectedRect.Left   = expectedAnchor.X;
                        expectedRect.Right  = expectedAnchor.X;
                        expectedRect.Bottom = expectedAnchor.Y;

                        // Now set up the keyboard and enter mark mode.
                        // NOTE: We must wait after every keyboard sequence to give the console time to process before asking it for changes.
                        area.EnterMode(ViewportArea.ViewportStates.Mark);

                        NativeMethods.Win32BoolHelper(WinCon.GetConsoleSelectionInfo(out csi), "Get state on entering mark mode.");
                        Log.Comment("Selection Info: {0}", csi);

                        Verify.AreEqual(csi.Flags, WinCon.CONSOLE_SELECTION_INFO_FLAGS.CONSOLE_SELECTION_IN_PROGRESS, "Selection should now be in progress since mark mode is started.");

                        // Select a small region
                        Log.Comment("1. Select a small region");

                        app.UIRoot.SendKeys(Keys.Shift + Keys.Right + Keys.Right + Keys.Right + Keys.Down + Keys.Shift);

                        Globals.WaitForTimeout();

                        // Adjust the expected rectangle for the commands we just entered.
                        expectedRect.Right  += 3; // same as the number of Rights we put in
                        expectedRect.Bottom += 1; // same as the number of Downs we put in

                        NativeMethods.Win32BoolHelper(WinCon.GetConsoleSelectionInfo(out csi), "Get state of selected region.");
                        Log.Comment("Selection Info: {0}", csi);

                        Verify.AreEqual(csi.Flags, WinCon.CONSOLE_SELECTION_INFO_FLAGS.CONSOLE_SELECTION_IN_PROGRESS | WinCon.CONSOLE_SELECTION_INFO_FLAGS.CONSOLE_SELECTION_NOT_EMPTY, "Selection in progress and is no longer empty now that we've selected a region.");
                        Verify.AreEqual(csi.Selection, expectedRect, "Verify that the selected rectangle matches the keystrokes we entered.");
                        Verify.AreEqual(csi.SelectionAnchor, expectedAnchor, "Verify anchor didn't go anywhere since we started in the top left.");

                        // End selection by moving
                        Log.Comment("2. End the selection by moving.");

                        app.UIRoot.SendKeys(Keys.Down);

                        Globals.WaitForTimeout();

                        NativeMethods.Win32BoolHelper(WinCon.GetConsoleSelectionInfo(out csi), "Move cursor to attempt to clear selection.");
                        Log.Comment("Selection Info: {0}", csi);

                        Verify.AreEqual(csi.Flags, WinCon.CONSOLE_SELECTION_INFO_FLAGS.CONSOLE_SELECTION_IN_PROGRESS, "Selection should be still running, but empty.");

                        // Select another region to ensure anchor moved.
                        Log.Comment("3. Select one more region from new position to verify anchor");

                        app.UIRoot.SendKeys(Keys.Shift + Keys.Right + Keys.Shift);

                        Globals.WaitForTimeout();

                        expectedAnchor.X = expectedRect.Right;
                        expectedAnchor.Y = expectedRect.Bottom;
                        expectedAnchor.Y++; // +1 for the Down in step 2. Not incremented in the line above because C# is unhappy with adding +1 to a short while assigning.

                        Verify.AreEqual(csi.SelectionAnchor, expectedAnchor, "Verify anchor moved to the new start position.");

                        // Exit mark mode
                        area.EnterMode(ViewportArea.ViewportStates.Normal);

                        NativeMethods.Win32BoolHelper(WinCon.GetConsoleSelectionInfo(out csi), "Move cursor to attempt to clear selection.");
                        Log.Comment("Selection Info: {0}", csi);

                        Verify.AreEqual(csi.Flags, WinCon.CONSOLE_SELECTION_INFO_FLAGS.CONSOLE_NO_SELECTION, "Selection should be empty when mode is exited.");
                    }
                }
            }
        }