Files
PowerShell-PSReadLine/UnitTestPSReadLine/UnitTestReadLine.cs
T
Jason Shirk c5351ddff7 Remove MinimumHistoryCommandLength
People seem to prefer all commands in history, so it seems better to have
fewer options.

The following can be used if the previous functionality is desired:

    Set-PSReadlineOption -AddToHistoryHandler { $args[0].Length -gt 3 }
2013-09-13 08:49:33 -07:00

1562 lines
60 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Reflection;
using System.Text;
using Microsoft.QualityTools.Testing.Fakes;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using PSConsoleUtilities;
namespace UnitTestPSReadLine
{
// Disgusting language hack to make it easier to read a sequence of keys.
using _ = Keys;
[TestClass]
public class UnitTest
{
static UnitTest()
{
var iss = InitialSessionState.CreateDefault2();
var rs = RunspaceFactory.CreateRunspace(iss);
rs.Open();
Runspace.DefaultRunspace = rs;
for (var i = 'a'; i <= 'z'; i++)
{
CharToKeyInfo[i] = new ConsoleKeyInfo(i, ConsoleKey.A + 'a' - i, false, false, false);
}
for (var i = 'A'; i <= 'Z'; i++)
{
CharToKeyInfo[i] = new ConsoleKeyInfo(i, ConsoleKey.A + 'A' - i, true, false, false);
}
for (var i = '0'; i <= '9'; i++)
{
CharToKeyInfo[i] = new ConsoleKeyInfo(i, ConsoleKey.D0 + '0' - i, false, false, false);
}
CharToKeyInfo['{'] = _.LCurly;
CharToKeyInfo['}'] = _.RCurly;
CharToKeyInfo['('] = _.LParen;
CharToKeyInfo[')'] = _.RParen;
CharToKeyInfo['['] = _.LBracket;
CharToKeyInfo[']'] = _.RBracket;
CharToKeyInfo[' '] = _.Space;
CharToKeyInfo['$'] = _.Dollar;
CharToKeyInfo['#'] = _.Pound;
CharToKeyInfo['<'] = _.LessThan;
CharToKeyInfo['>'] = _.GreaterThan;
CharToKeyInfo['+'] = _.Plus;
CharToKeyInfo['-'] = _.Minus;
CharToKeyInfo['_'] = _.Underbar;
CharToKeyInfo['|'] = _.Pipe;
CharToKeyInfo[';'] = _.Semicolon;
CharToKeyInfo['"'] = _.DQuote;
CharToKeyInfo['\''] = _.SQuote;
CharToKeyInfo['\n'] = new ConsoleKeyInfo('\r', ConsoleKey.Enter, false, false, false);
CharToKeyInfo['\r'] = new ConsoleKeyInfo('\r', ConsoleKey.Enter, false, false, false);
}
private enum KeyMode
{
Cmd,
Emacs,
#if FALSE
Vi
#endif
};
// These colors are random - we just use these colors instead of the defaults
// so the tests aren't sensitive to tweaks to the default colors.
private static readonly ConsoleColor[] ForegroundColors = new []
{
/*None*/ Console.ForegroundColor,
/*Comment*/ ConsoleColor.Blue,
/*Keyword*/ ConsoleColor.Cyan,
/*String*/ ConsoleColor.Gray,
/*Operator*/ ConsoleColor.Green,
/*Variable*/ ConsoleColor.Magenta,
/*Command*/ ConsoleColor.Red,
/*Parameter*/ ConsoleColor.White,
/*Type*/ ConsoleColor.Yellow,
/*Number*/ ConsoleColor.DarkBlue,
};
private static readonly ConsoleColor[] BackgroundColors = new[]
{
/*None*/ Console.BackgroundColor,
/*Comment*/ ConsoleColor.DarkBlue,
/*Keyword*/ ConsoleColor.DarkCyan,
/*String*/ ConsoleColor.DarkGray,
/*Operator*/ ConsoleColor.DarkGreen,
/*Variable*/ ConsoleColor.DarkMagenta,
/*Command*/ ConsoleColor.DarkRed,
/*Parameter*/ ConsoleColor.DarkYellow,
/*Type*/ ConsoleColor.Black,
/*Number*/ ConsoleColor.Gray,
};
static Dictionary<char, ConsoleKeyInfo> CharToKeyInfo = new Dictionary<char, ConsoleKeyInfo>();
class KeyHandler
{
public KeyHandler(string chord, Action<ConsoleKeyInfo?, object> handler)
{
this.Chord = chord;
this.Handler = handler;
}
public string Chord { get; private set; }
public Action<ConsoleKeyInfo?, object> Handler { get; private set; }
}
class KeyWithValidation
{
public KeyWithValidation(ConsoleKeyInfo key, Action validator = null)
{
this.Key = key;
this.Validator = validator;
}
public ConsoleKeyInfo Key { get; set; }
public Action Validator { get; set; }
}
class CancelReadLineException : Exception
{
public static void Throw()
{
throw new CancelReadLineException();
}
}
private void AssertCursorLeftTopIs(int left, int top)
{
AssertCursorLeftIs(left);
AssertCursorTopIs(top);
}
private void AssertCursorLeftIs(int expected)
{
Assert.AreEqual(expected, Console.CursorLeft);
}
private void AssertCursorTopIs(int expected)
{
Assert.AreEqual(expected, Console.CursorTop);
}
private void AssertLineIs(string expected)
{
string input;
int unused;
PSConsoleReadLine.GetBufferState(out input, out unused);
Assert.AreEqual(expected, input);
}
private class NextLineToken { }
static NextLineToken NextLine = new NextLineToken();
private CHAR_INFO[] CreateCharInfoBuffer(params object[] items)
{
var result = new List<CHAR_INFO>();
var fg = Console.ForegroundColor;
var bg = Console.BackgroundColor;
foreach (var i in items)
{
var item = i;
if (item is char)
{
result.Add(new CHAR_INFO((char)item, fg, bg));
continue;
}
if (item is NextLineToken)
{
item = new string(' ', Console.BufferWidth - (result.Count % Console.BufferWidth));
fg = Console.ForegroundColor;
bg = Console.BackgroundColor;
// Fallthrough to string case.
}
var str = item as string;
if (str != null)
{
result.AddRange(str.Select(c => new CHAR_INFO(c, fg, bg)));
continue;
}
if (item is TokenClassification)
{
fg = ForegroundColors[(int)(TokenClassification)item];
bg = BackgroundColors[(int)(TokenClassification)item];
continue;
}
var tuple = item as Tuple<ConsoleColor, ConsoleColor>;
if (tuple != null)
{
fg = tuple.Item1;
bg = tuple.Item2;
continue;
}
throw new ArgumentException("Unexpected type");
}
var extraSpacesNeeded = Console.BufferWidth - (result.Count % Console.BufferWidth);
if (extraSpacesNeeded != 0)
{
var space = new CHAR_INFO(' ', Console.ForegroundColor, Console.BackgroundColor);
result.AddRange(Enumerable.Repeat(space, extraSpacesNeeded));
}
return result.ToArray();
}
static private KeyWithValidation[] Keys(params object[] input)
{
var list = new List<KeyWithValidation>();
foreach (var t in input)
{
if (t is ConsoleKeyInfo)
{
list.Add(new KeyWithValidation((ConsoleKeyInfo)t));
}
else if (t is string)
{
foreach (var c in (string)t)
{
list.Add(new KeyWithValidation(CharToKeyInfo[c]));
}
}
else if (t is char)
{
list.Add(new KeyWithValidation(CharToKeyInfo[(char)t]));
}
else
{
list.Add((KeyWithValidation)t);
}
}
return list.ToArray();
}
private static CHAR_INFO[] ReadBufferLines(int top, int count)
{
var result = new CHAR_INFO[Console.BufferWidth * count];
var handle = NativeMethods.GetStdHandle((uint) StandardHandleId.Output);
var readBufferSize = new COORD {
X = (short)Console.BufferWidth,
Y = (short)count};
var readBufferCoord = new COORD {X = 0, Y = 0};
var readRegion = new SMALL_RECT
{
Top = (short)top,
Left = 0,
Bottom = (short)(top + count),
Right = (short)(Console.BufferWidth - 1)
};
NativeMethods.ReadConsoleOutput(handle, result,
readBufferSize, readBufferCoord, ref readRegion);
return result;
}
private static void ScrollBuffer(int lines)
{
var handle = NativeMethods.GetStdHandle((uint) StandardHandleId.Output);
var scrollRectangle = new SMALL_RECT
{
Top = (short) lines,
Left = 0,
Bottom = (short) (lines + Console.BufferHeight - 1),
Right = (short)Console.BufferWidth
};
var destinationOrigin = new COORD {X = 0, Y = 0};
var fillChar = new CHAR_INFO(' ', Console.ForegroundColor, Console.BackgroundColor);
NativeMethods.ScrollConsoleScreenBuffer(handle, ref scrollRectangle, ref scrollRectangle, destinationOrigin, ref fillChar);
}
private static void WriteBufferLines(CHAR_INFO[] buffer, ref int top)
{
var handle = NativeMethods.GetStdHandle((uint) StandardHandleId.Output);
int bufferWidth = Console.BufferWidth;
int bufferLineCount = buffer.Length / bufferWidth;
if ((top + bufferLineCount) > Console.BufferHeight)
{
var scrollCount = (top + bufferLineCount) - Console.BufferHeight;
ScrollBuffer(scrollCount);
top -= scrollCount;
}
var bufferSize = new COORD
{
X = (short) bufferWidth,
Y = (short) bufferLineCount
};
var bufferCoord = new COORD {X = 0, Y = 0};
var writeRegion = new SMALL_RECT
{
Top = (short) top,
Left = 0,
Bottom = (short) (top + bufferLineCount - 1),
Right = (short) bufferWidth
};
NativeMethods.WriteConsoleOutput(handle, buffer,
bufferSize, bufferCoord, ref writeRegion);
}
private void AssertScreenIs(int lines, params object[] items)
{
var consoleBuffer = ReadBufferLines(0, lines);
var expectedBuffer = CreateCharInfoBuffer(items);
Assert.AreEqual(expectedBuffer.Length, consoleBuffer.Length);
for (var i = 0; i < expectedBuffer.Length; i++)
{
Assert.AreEqual(expectedBuffer[i], consoleBuffer[i]);
}
}
static void SetBufferState(string text, int cursor)
{
var keys = new List<KeyWithValidation>();
keys.AddRange(Keys(text));
keys.Add(new KeyWithValidation(_.Home));
while (cursor-- > 0)
{
keys.Add(new KeyWithValidation(_.RightArrow));
}
keys.Last().Validator = CancelReadLineException.Throw;
Test(keys.ToArray());
}
static void ClearScreen()
{
int bufferWidth = Console.BufferWidth;
const int bufferLineCount = 10;
var consoleBuffer = new CHAR_INFO[bufferWidth * bufferLineCount];
for (int i = 0; i < consoleBuffer.Length; i++)
{
consoleBuffer[i] = new CHAR_INFO(' ', Console.ForegroundColor, Console.BackgroundColor);
}
int top = 0;
WriteBufferLines(consoleBuffer, ref top);
}
static private void SetPrompt(string prompt)
{
if (string.IsNullOrEmpty(prompt))
return;
var handle = NativeMethods.GetStdHandle((uint) StandardHandleId.Output);
var lineCount = 1 + prompt.Count(c => c == '\n');
if (lineCount > 1)
{
var options = new SetPSReadlineOption {ExtraPromptLineCount = lineCount - 1};
PSConsoleReadLine.SetOptions(options);
}
int bufferWidth = Console.BufferWidth;
var consoleBuffer = new CHAR_INFO[lineCount * bufferWidth];
int j = 0;
for (int i = 0; i < prompt.Length; i++, j++)
{
if (prompt[i] == '\n')
{
for (; j % Console.BufferWidth != 0; j++)
{
consoleBuffer[j] = new CHAR_INFO(' ', Console.ForegroundColor, Console.BackgroundColor);
}
Console.CursorTop += 1;
Console.CursorLeft = 0;
j -= 1; // We don't actually write the newline
}
else
{
consoleBuffer[j] = new CHAR_INFO(prompt[i], Console.ForegroundColor, Console.BackgroundColor);
Console.CursorLeft += 1;
}
}
var bufferSize = new COORD
{
X = (short) bufferWidth,
Y = (short) lineCount
};
var bufferCoord = new COORD {X = 0, Y = 0};
var writeRegion = new SMALL_RECT
{
Top = 0,
Left = 0,
Bottom = (short) (lineCount - 1),
Right = (short) bufferWidth
};
NativeMethods.WriteConsoleOutput(handle, consoleBuffer, bufferSize, bufferCoord, ref writeRegion);
}
static private string Test(KeyWithValidation[] keys, string prompt = null)
{
Console.CursorLeft = 0;
Console.CursorTop = 0;
SetPrompt(prompt);
int index = 0;
try
{
using (ShimsContext.Create())
{
PSConsoleUtilities.Fakes.ShimPSConsoleReadLine.ReadKey = () => keys[index].Key;
PSConsoleUtilities.Fakes.ShimPSConsoleReadLine.PostKeyHandler = () =>
{
if (keys[index].Validator != null)
{
keys[index].Validator();
}
index++;
};
System.Management.Automation.Fakes.ShimCommandCompletion.CompleteInputStringInt32HashtablePowerShell =
MockedCompleteInput;
return PSConsoleReadLine.ReadLine();
}
}
catch (CancelReadLineException)
{
return null;
}
}
private string Test(ConsoleKeyInfo[] keys, string prompt = null)
{
Console.CursorLeft = 0;
Console.CursorTop = 0;
SetPrompt(prompt);
int index = 0;
using (ShimsContext.Create())
{
PSConsoleUtilities.Fakes.ShimPSConsoleReadLine.ReadKey = () => keys[index++];
System.Management.Automation.Fakes.ShimCommandCompletion.CompleteInputStringInt32HashtablePowerShell =
MockedCompleteInput;
return PSConsoleReadLine.ReadLine();
}
}
private void TestSetup(KeyMode keyMode, params KeyHandler[] keyHandlers)
{
ClearScreen();
PSConsoleReadLine.ClearHistory();
PSConsoleReadLine.ClearKillRing();
var options = new SetPSReadlineOption
{
AddToHistoryHandler = null,
HistoryNoDuplicates = PSConsoleReadLine.DefaultHistoryNoDuplicates,
MaximumHistoryCount = PSConsoleReadLine.DefaultMaximumHistoryCount,
MaximumKillRingCount = PSConsoleReadLine.DefaultMaximumKillRingCount,
ResetTokenColors = true,
};
switch (keyMode)
{
case KeyMode.Cmd:
options.EditMode = EditMode.Windows;
break;
case KeyMode.Emacs:
options.EditMode = EditMode.Emacs;
break;
#if FALSE
case KeyMode.Vi:
options.EditMode = EditMode.Vi;
break;
#endif
}
PSConsoleReadLine.SetOptions(options);
foreach (var keyHandler in keyHandlers)
{
PSConsoleReadLine.SetKeyHandler(new [] {keyHandler.Chord}, keyHandler.Handler, "", "");
}
var colorOptions = new SetPSReadlineOption();
foreach (var val in typeof(TokenClassification).GetEnumValues())
{
colorOptions.TokenKind = (TokenClassification)val;
colorOptions.ForegroundColor = ForegroundColors[(int)val];
colorOptions.BackgroundColor = BackgroundColors[(int)val];
PSConsoleReadLine.SetOptions(colorOptions);
}
}
[TestMethod]
public void TestInput()
{
TestSetup(KeyMode.Cmd);
var keys = Keys("exit", _.Enter);
var result = Test(keys); Assert.AreEqual("exit", result);
AssertCursorLeftIs(4);
}
[TestMethod]
public void TestLongLine()
{
TestSetup(KeyMode.Cmd);
var width = Console.BufferWidth;
var sb = new StringBuilder();
var keys = new ConsoleKeyInfo[width + 3];
int i = 0;
keys[i++] = _.DQuote;
sb.Append('"');
while (i < width + 1)
{
keys[i++] = _.Z;
sb.Append('z');
}
keys[i++] = _.DQuote;
sb.Append('"');
keys[i] = _.Enter;
var result = Test(keys); Assert.AreEqual(sb.ToString(), result);
}
[TestMethod]
public void TestEndOfLine()
{
TestSetup(KeyMode.Cmd);
var keys = Keys(
new KeyWithValidation(_.End, () => AssertCursorLeftIs(0)),
new KeyWithValidation(_.Enter)
);
var result = Test(keys); Assert.AreEqual("", result);
TestSetup(KeyMode.Cmd);
var width = Console.BufferWidth;
var buffer = new StringBuilder();
keys = new KeyWithValidation[width * 3];
int i = 0;
while (i < width)
{
keys[i++] = new KeyWithValidation(_.Space);
buffer.Append(' ');
}
keys[i++] = new KeyWithValidation(_.Home, () => AssertCursorLeftIs(0));
keys[i++] = new KeyWithValidation(_.End, () => AssertCursorLeftTopIs(0, 1));
keys[i] = new KeyWithValidation(_.Enter);
result = Test(keys); Assert.AreEqual(buffer.ToString(), result);
for (int j = 0; j < 5; j++)
{
keys[i++] = new KeyWithValidation(_.Space);
buffer.Append(' ');
}
keys[i++] = new KeyWithValidation(_.Home, () => AssertCursorLeftIs(0));
keys[i++] = new KeyWithValidation(_.End, () => AssertCursorLeftTopIs(5, 1));
keys[i] = new KeyWithValidation(_.Enter);
result = Test(keys); Assert.AreEqual(buffer.ToString(), result);
}
[TestMethod]
public void TestCursorMovement()
{
TestSetup(KeyMode.Cmd);
var keysWithValidation = Keys(
new KeyWithValidation(_.LeftArrow, () => AssertCursorLeftIs(0)),
"ace",
new KeyWithValidation(_.LeftArrow, () => AssertCursorLeftIs(2)),
'd',
new KeyWithValidation(_.LeftArrow, () => AssertCursorLeftIs(2)),
new KeyWithValidation(_.LeftArrow, () => AssertCursorLeftIs(1)),
'b', _.Enter
);
var result = Test(keysWithValidation); Assert.AreEqual("abcde", result);
}
[TestMethod]
public void TestMultiLine()
{
TestSetup(KeyMode.Cmd);
var keysWithValidation = Keys(
"d|",
new KeyWithValidation(_.Enter, () => AssertCursorTopIs(1)),
'd', _.Enter
);
var result = Test(keysWithValidation); Assert.AreEqual("d|\nd", result);
// Make sure <ENTER> when input is incomplete actually puts a newline
// wherever the cursor is.
var continationPrefixLength = PSConsoleReadLine.DefaultContinuationPrompt.Length;
keysWithValidation = Keys(
'{',
new KeyWithValidation(_.Enter, () => AssertCursorTopIs(1)),
'd',
new KeyWithValidation(_.Enter, () => AssertCursorTopIs(2)),
new KeyWithValidation(_.Home),
new KeyWithValidation(_.RightArrow, () => AssertCursorLeftTopIs(1, 0)),
new KeyWithValidation(_.Enter, () => AssertCursorLeftTopIs(continationPrefixLength, 1)),
new KeyWithValidation(_.End, () => AssertCursorLeftTopIs(continationPrefixLength, 3)),
'}', _.Enter
);
result = Test(keysWithValidation); Assert.AreEqual("{\n\nd\n}", result);
// Make sure <ENTER> when input successfully parses accepts the input regardless
// of where the cursor is, plus it moves the cursor to the end (so the new prompt
// doesn't overwrite the end of the previous long/multi-line command line.)
keysWithValidation = Keys(
'{',
new KeyWithValidation(_.Enter),
'}',
new KeyWithValidation(_.Home),
new KeyWithValidation(_.Enter, () => AssertCursorLeftTopIs(continationPrefixLength + 1, 1))
);
result = Test(keysWithValidation); Assert.AreEqual("{\n}", result);
}
[TestMethod]
public void TestDelete()
{
TestSetup(KeyMode.Cmd);
// Empty input (does nothing, but don't crash)
var keys = Keys(_.Delete, _.Enter);
var result = Test(keys); Assert.AreEqual("", result);
// At end but input not empty (does nothing, but don't crash)
keys = Keys('a', _.Delete, _.Enter);
result = Test(keys); Assert.AreEqual("a", result);
// Delete last character
keys = Keys("ab", _.LeftArrow, _.Delete, _.Enter);
result = Test(keys); Assert.AreEqual("a", result);
// Delete first character
keys = Keys("ab", _.Home, _.Delete, _.Enter);
result = Test(keys); Assert.AreEqual("b", result);
// Delete middle character
keys = Keys("abc", _.Home, _.RightArrow, _.Delete, _.Enter);
result = Test(keys); Assert.AreEqual("ac", result);
}
[TestMethod]
public void TestBackspace()
{
TestSetup(KeyMode.Cmd);
// Empty input (does nothing but don't crash)
var keys = new [] {_.Backspace, _.Enter};
var result = Test(keys); Assert.AreEqual("", result);
// At end, delete all input
keys = new [] {_.A, _.Backspace, _.Enter};
result = Test(keys); Assert.AreEqual("", result);
// At end, delete all input with extra backspaces
keys = new [] {_.A, _.Backspace, _.Backspace, _.Enter};
result = Test(keys); Assert.AreEqual("", result);
// Delete first character
keys = new [] {_.A, _.B, _.LeftArrow, _.Backspace, _.Enter};
result = Test(keys); Assert.AreEqual("b", result);
// Delete first character with extra backspaces
keys = new [] {_.A, _.B, _.LeftArrow, _.Backspace, _.Backspace, _.Enter};
result = Test(keys); Assert.AreEqual("b", result);
// Delete middle character
keys = new [] {_.A, _.B, _.C, _.LeftArrow, _.Backspace, _.Enter};
result = Test(keys); Assert.AreEqual("ac", result);
}
[TestMethod]
public void TestForwardDeleteLine()
{
TestSetup(KeyMode.Cmd);
// Empty input (does nothing but don't crash)
var keys = Keys(_.CtrlEnd, _.Enter);
var result = Test(keys); Assert.AreEqual("", result);
// at end of input - doesn't change anything
keys = Keys("abc", _.CtrlEnd, _.Enter);
result = Test(keys); Assert.AreEqual("abc", result);
keys = Keys("abc", _.LeftArrow, _.LeftArrow, _.CtrlEnd, _.Enter);
result = Test(keys); Assert.AreEqual("a", result);
}
[TestMethod]
public void TestBackwardDeleteLine()
{
TestSetup(KeyMode.Cmd);
// Empty input (does nothing but don't crash)
var keys = Keys(_.CtrlHome, _.Enter);
var result = Test(keys); Assert.AreEqual("", result);
// at beginning of input - doesn't change anything
keys = Keys("abc", _.Home, _.CtrlHome, _.Enter);
result = Test(keys); Assert.AreEqual("abc", result);
keys = Keys("abc", _.LeftArrow, _.CtrlHome, _.Enter);
result = Test(keys); Assert.AreEqual("c", result);
}
[TestMethod]
public void TestAddLine()
{
TestSetup(KeyMode.Cmd);
var keys = new[] {_._1, _.ShiftEnter, _._2, _.Enter};
var result = Test(keys); Assert.AreEqual("1\n2", result);
}
[TestMethod]
public void TestIgnore()
{
TestSetup(KeyMode.Emacs);
var keys = new[] {_.A, _.VolumeDown, _.VolumeMute, _.VolumeUp, _.B, _.Enter};
var result = Test(keys); Assert.AreEqual("ab", result);
}
[TestMethod]
public void TestTabComplete()
{
TestSetup(KeyMode.Cmd);
var keys = new [] {_.Dollar, _.T, _.R, _.Tab, _.Enter};
var result = Test(keys); Assert.AreEqual("$true", result);
AssertCursorLeftIs(5);
// Validate no change on no match
keys = new [] {_.Dollar, _.Z, _.Z, _.Tab, _.Enter};
result = Test(keys); Assert.AreEqual("$zz", result);
AssertCursorLeftIs(3);
var keysWithValidation = new []
{
new KeyWithValidation(_.Dollar),
new KeyWithValidation(_.T),
new KeyWithValidation(_.Tab, () => AssertLineIs("$this")),
new KeyWithValidation(_.Tab, () => AssertLineIs("$true")),
new KeyWithValidation(_.Tab, () => AssertLineIs("$this")),
new KeyWithValidation(_.ShiftTab, () => AssertLineIs("$true")),
new KeyWithValidation(_.Enter),
};
result = Test(keysWithValidation); Assert.AreEqual("$true", result);
}
[TestMethod]
public void TestComplete()
{
TestSetup(KeyMode.Emacs);
var keys = Keys("ambig",
new KeyWithValidation(_.Tab, () => AssertLineIs("ambiguous")),
"1", _.Enter);
var result = Test(keys); Assert.AreEqual("ambiguous1", result);
}
[TestMethod]
public void TestHistory()
{
TestSetup(KeyMode.Cmd);
// No history
var keys = new [] {_.UpArrow, _.DownArrow, _.Enter};
var result = Test(keys); Assert.AreEqual("", result);
keys = new [] {_.D, _.I, _.R, _.Space, _.C, _.Star, _.Enter};
result = Test(keys); Assert.AreEqual("dir c*", result);
keys = new [] {_.P, _.S, _.Space, _.P, _.Star, _.Enter};
result = Test(keys); Assert.AreEqual("ps p*", result);
keys = new [] {_.UpArrow, _.UpArrow, _.Enter};
result = Test(keys); Assert.AreEqual("dir c*", result);
keys = new [] {_.UpArrow, _.UpArrow, _.DownArrow, _.Enter};
result = Test(keys); Assert.AreEqual("dir c*", result);
}
[TestMethod]
public void TestSearchHistory()
{
TestSetup(KeyMode.Cmd,
new KeyHandler("UpArrow", PSConsoleReadLine.HistorySearchBackward),
new KeyHandler("DownArrow", PSConsoleReadLine.HistorySearchForward));
// No history
var keys = new [] {_.UpArrow, _.DownArrow, _.Enter};
var result = Test(keys); Assert.AreEqual("", result);
// Clear history in case the above added some history (but it shouldn't)
PSConsoleReadLine.ClearHistory();
keys = new [] {_.Space, _.UpArrow, _.DownArrow, _.Enter};
result = Test(keys); Assert.AreEqual(" ", result);
keys = new [] {_.D, _.I, _.R, _.Space, _.C, _.Star, _.Enter};
result = Test(keys); Assert.AreEqual("dir c*", result);
keys = new [] {_.P, _.S, _.Space, _.P, _.Star, _.Enter};
result = Test(keys); Assert.AreEqual("ps p*", result);
keys = new [] {_.D, _.I, _.R, _.Space, _.C, _.D, _.Star, _.Enter};
result = Test(keys); Assert.AreEqual("dir cd*", result);
var keysWithValidation = new []
{
new KeyWithValidation(_.D),
new KeyWithValidation(_.UpArrow, () => AssertCursorLeftIs(1)),
new KeyWithValidation(_.UpArrow, () => AssertCursorLeftIs(1)),
new KeyWithValidation(_.DownArrow, () => AssertCursorLeftIs(1)),
new KeyWithValidation(_.UpArrow, () => AssertCursorLeftIs(1)),
new KeyWithValidation(_.Enter)
};
result = Test(keysWithValidation); Assert.AreEqual("dir c*", result);
PSConsoleReadLine.SetOptions(new SetPSReadlineOption {HistorySearchCursorMovesToEnd = true});
keysWithValidation = new []
{
new KeyWithValidation(_.D),
new KeyWithValidation(_.UpArrow, () => AssertCursorLeftIs(6)),
new KeyWithValidation(_.UpArrow, () => AssertCursorLeftIs(7)),
new KeyWithValidation(_.DownArrow, () => AssertCursorLeftIs(6)),
new KeyWithValidation(_.UpArrow, () => AssertCursorLeftIs(7)),
new KeyWithValidation(_.Enter)
};
result = Test(keysWithValidation); Assert.AreEqual("dir cd*", result);
}
[TestMethod]
public void TestAddToHistoryHandler()
{
TestSetup(KeyMode.Cmd);
PSConsoleReadLine.SetOptions(new SetPSReadlineOption {AddToHistoryHandler = s => s.StartsWith("z")});
var keys = new [] {_.Z, _.Z, _.Z, _.Z, _.Enter};
var result = Test(keys); Assert.AreEqual("zzzz", result);
keys = new [] {_.A, _.Z, _.Z, _.Z, _.Enter};
result = Test(keys); Assert.AreEqual("azzz", result);
keys = new [] {_.UpArrow, _.Enter};
result = Test(keys); Assert.AreEqual("zzzz", result);
}
[TestMethod]
public void TestHistoryDuplicates()
{
TestSetup(KeyMode.Cmd);
PSConsoleReadLine.SetOptions(new SetPSReadlineOption {HistoryNoDuplicates = false});
var keys0 = new [] {_.Z, _.Z, _.Z, _.Z, _.Enter};
var keys1 = new [] {_.A, _.A, _.A, _.A, _.Enter};
var keys2 = new [] {_.B, _.B, _.B, _.B, _.Enter};
var keys3 = new [] {_.C, _.C, _.C, _.C, _.Enter};
var result = Test(keys0); Assert.AreEqual("zzzz", result);
result = Test(keys1); Assert.AreEqual("aaaa", result);
result = Test(keys2); Assert.AreEqual("bbbb", result);
result = Test(keys2); Assert.AreEqual("bbbb", result);
result = Test(keys3); Assert.AreEqual("cccc", result);
var keys4 = new [] {_.UpArrow, _.UpArrow, _.UpArrow, _.UpArrow, _.Enter};
result = Test(keys4); Assert.AreEqual("aaaa", result);
PSConsoleReadLine.SetOptions(new SetPSReadlineOption {HistoryNoDuplicates = true});
var keys5 = new [] {_.UpArrow, _.UpArrow, _.UpArrow, _.Enter};
result = Test(keys5); Assert.AreEqual("aaaa", result);
PSConsoleReadLine.ClearHistory();
result = Test(keys1); Assert.AreEqual("aaaa", result);
result = Test(keys2); Assert.AreEqual("bbbb", result);
result = Test(keys2); Assert.AreEqual("bbbb", result);
result = Test(keys3); Assert.AreEqual("cccc", result);
keys5 = new [] {_.UpArrow, _.UpArrow, _.UpArrow, _.Enter};
result = Test(keys5); Assert.AreEqual("aaaa", result);
}
[TestMethod]
public void TestHistoryCount()
{
TestSetup(KeyMode.Cmd);
var keys0 = new [] {_.Z, _.Z, _.Z, _.Z, _.Enter};
var keys1 = new [] {_.A, _.A, _.A, _.A, _.Enter};
var keys2 = new [] {_.B, _.B, _.B, _.B, _.Enter};
var keys3 = new [] {_.C, _.C, _.C, _.C, _.Enter};
var result = Test(keys0); Assert.AreEqual("zzzz", result);
result = Test(keys1); Assert.AreEqual("aaaa", result);
result = Test(keys2); Assert.AreEqual("bbbb", result);
result = Test(keys3); Assert.AreEqual("cccc", result);
PSConsoleReadLine.SetOptions(new SetPSReadlineOption {MaximumHistoryCount = 3});
var keys4 = new [] {_.UpArrow, _.UpArrow, _.UpArrow, _.UpArrow, _.Enter};
result = Test(keys4); Assert.AreEqual("aaaa", result);
result = Test(keys0); Assert.AreEqual("zzzz", result);
result = Test(keys0); Assert.AreEqual("zzzz", result);
result = Test(keys0); Assert.AreEqual("zzzz", result);
result = Test(keys1); Assert.AreEqual("aaaa", result);
result = Test(keys2); Assert.AreEqual("bbbb", result);
result = Test(keys3); Assert.AreEqual("cccc", result);
result = Test(keys4); Assert.AreEqual("aaaa", result);
}
[TestMethod]
public void TestYankPop()
{
TestSetup(KeyMode.Emacs);
var killedText = new List<string>();
var keys = new[] {_.CtrlY, _.AltY, _.Z, _.Enter};
var result = Test(keys); Assert.AreEqual("z", result);
// Fill the kill ring plus some extra.
keys = new [] {_.Z, _.Z, _.Z, _.CtrlU, _.Enter};
for (int i = 0; i < PSConsoleReadLine.DefaultMaximumKillRingCount + 2; i++)
{
var c = (char)('a' + i);
var k = (ConsoleKey)((int)ConsoleKey.A + i);
killedText.Add(c + "zz");
keys[0] = new ConsoleKeyInfo(c, k, false, false, false);
result = Test(keys); Assert.AreEqual("", result);
}
int killRingIndex = killedText.Count - 1;
keys = new [] {_.CtrlY, _.Enter};
result = Test(keys); Assert.AreEqual(killedText[killRingIndex], result);
keys = new [] {_.CtrlY, _.CtrlY, _.Enter};
result = Test(keys); Assert.AreEqual(killedText[killRingIndex] + killedText[killRingIndex], result);
killRingIndex -= 1;
keys = new [] {_.CtrlY, _.AltY, _.Enter};
result = Test(keys); Assert.AreEqual(killedText[killRingIndex], result);
// Test wrap around. We need 1 yank and n-1 yankpop to wrap around once, plus enter.
keys = new ConsoleKeyInfo[PSConsoleReadLine.DefaultMaximumKillRingCount + 2];
keys[0] = _.CtrlY;
keys[keys.Length - 1] = _.Enter;
for (int i = 1; i <= keys.Length - 2; i++)
{
keys[i] = _.AltY;
}
result = Test(keys); Assert.AreEqual(killedText[killRingIndex], result);
// Make sure an empty kill doesn't end up in the kill ring
keys = new [] {_.A, _.CtrlU, _.CtrlU, _.B, _.CtrlU, _.CtrlY, _.AltY, _.Enter};
result = Test(keys); Assert.AreEqual("a", result);
}
[TestMethod]
public void TestKillLine()
{
TestSetup(KeyMode.Emacs);
var keys = new [] {_.D, _.I, _.R, _.CtrlA, _.CtrlK, _.Enter};
var result = Test(keys); Assert.AreEqual("", result);
keys = new [] {_.CtrlY, _.Enter};
result = Test(keys); Assert.AreEqual("dir", result);
}
[TestMethod]
public void TestBackwardKillLine()
{
TestSetup(KeyMode.Emacs);
var keys = new [] {_.D, _.I, _.R, _.CtrlU, _.L, _.S, _.Enter};
var result = Test(keys); Assert.AreEqual("ls", result);
keys = new [] {_.CtrlY, _.Enter};
result = Test(keys); Assert.AreEqual("dir", result);
keys = new [] {_.A, _.B, _.C, _.CtrlX, _.Backspace, _.D, _.E, _.F, _.Enter};
result = Test(keys); Assert.AreEqual("def", result);
}
[TestMethod]
public void TestKillAppend()
{
TestSetup(KeyMode.Emacs);
var keys = Keys(" abcdir", _.LeftArrow, _.LeftArrow, _.LeftArrow,
_.CtrlK, // Kill 'dir'
_.CtrlU, // Kill append ' abc'
_.CtrlY, // Yank 'dir abc'
_.Enter);
var result = Test(keys);
Assert.AreEqual("dir abc", result);
// Test empty kill doesn't affect kill append
keys = Keys("ab", _.LeftArrow, _.CtrlK, _.CtrlK, _.CtrlU, _.CtrlY, _.Enter);
result = Test(keys); Assert.AreEqual("ba", result);
}
[TestMethod]
public void TestKillWord()
{
TestSetup(KeyMode.Emacs);
var keys = Keys(_.AltD, // Test on empty input
"echo abc def", _.LeftArrow, _.LeftArrow, _.LeftArrow, _.LeftArrow, _.LeftArrow, _.LeftArrow, _.LeftArrow,
_.AltD, // Kill 'abc'
_.End, _.CtrlY, // Yank 'abc' at end of line
_.Enter);
var result = Test(keys); Assert.AreEqual("echo defabc", result);
}
[TestMethod]
public void TestKillBackwardWord()
{
TestSetup(KeyMode.Emacs);
var keys = Keys(_.AltBackspace, // Test on empty line
"echo abc def", _.LeftArrow, _.LeftArrow, _.LeftArrow,
_.AltBackspace, // Kill 'abc '
_.End, _.CtrlY, // Yank 'abc ' at the end
_.Enter);
var result = Test(keys);
Assert.AreEqual("echo defabc ", result);
}
[TestMethod]
public void TestRevertLine()
{
// Add one test for chords
TestSetup(KeyMode.Cmd, new KeyHandler("Ctrl+X,Escape", PSConsoleReadLine.RevertLine));
var keys = new [] {_.D, _.I, _.Escape, _.L, _.S, _.Enter};
var result = Test(keys); Assert.AreEqual("ls", result);
keys = new [] {_.D, _.I, _.CtrlX, _.Escape, _.L, _.S, _.Enter};
result = Test(keys); Assert.AreEqual("ls", result);
TestSetup(KeyMode.Emacs);
keys = new [] {_.D, _.I, _.Escape, _.R, _.L, _.S, _.Enter};
result = Test(keys); Assert.AreEqual("ls", result);
keys = new [] {_.D, _.I, _.AltR, _.L, _.S, _.Enter};
result = Test(keys); Assert.AreEqual("ls", result);
}
[TestMethod]
public void TestForwardWord()
{
TestSetup(KeyMode.Cmd);
var keys = new[]
{
new KeyWithValidation(_.CtrlRightArrow, () => AssertCursorLeftIs(0)),
new KeyWithValidation(_.A),
new KeyWithValidation(_.A),
new KeyWithValidation(_.A),
new KeyWithValidation(_.Space),
new KeyWithValidation(_.Space),
new KeyWithValidation(_.B),
new KeyWithValidation(_.B),
new KeyWithValidation(_.B),
new KeyWithValidation(_.Space),
new KeyWithValidation(_.Space),
new KeyWithValidation(_.C),
new KeyWithValidation(_.C),
new KeyWithValidation(_.C),
new KeyWithValidation(_.Home, () => AssertCursorLeftIs(0)),
new KeyWithValidation(_.CtrlRightArrow, () => AssertCursorLeftIs(5)),
new KeyWithValidation(_.LeftArrow),
new KeyWithValidation(_.LeftArrow),
new KeyWithValidation(_.CtrlRightArrow, () => AssertCursorLeftIs(5)),
new KeyWithValidation(_.LeftArrow),
new KeyWithValidation(_.CtrlRightArrow, () => AssertCursorLeftIs(5)),
new KeyWithValidation(_.CtrlRightArrow, () => AssertCursorLeftIs(10)),
new KeyWithValidation(_.CtrlRightArrow, () => AssertCursorLeftIs(13)),
new KeyWithValidation(_.Home, CancelReadLineException.Throw)
};
Test(keys);
keys = Keys("echo \"a $b c $d e\" 42",
_.Home, _.RightArrow, _.RightArrow, _.RightArrow, _.RightArrow, _.RightArrow,
new KeyWithValidation(_.CtrlRightArrow, () => AssertCursorLeftIs(8)),
new KeyWithValidation(_.CtrlRightArrow, () => AssertCursorLeftIs(13)),
new KeyWithValidation(_.CtrlRightArrow, () => AssertCursorLeftIs(19)),
new KeyWithValidation(_.Home, CancelReadLineException.Throw));
Test(keys);
}
[TestMethod]
public void TestBackwardWord()
{
TestSetup(KeyMode.Cmd);
const string input = " aaa bbb ccc ";
var keysWithValidation = Keys(
new KeyWithValidation(_.CtrlLeftArrow, () => AssertCursorLeftIs(0)),
input,
new KeyWithValidation(_.CtrlLeftArrow, () => AssertCursorLeftIs(12)),
new KeyWithValidation(_.CtrlLeftArrow, () => AssertCursorLeftIs(7)),
new KeyWithValidation(_.CtrlLeftArrow, () => AssertCursorLeftIs(2)),
new KeyWithValidation(_.CtrlLeftArrow, () => AssertCursorLeftIs(0)),
_.Enter
);
var result = Test(keysWithValidation); Assert.AreEqual(input, result);
}
[TestMethod]
public void TestEmacsBackwardWord()
{
TestSetup(KeyMode.Emacs);
const string input = " aaa bbb ccc ";
var keysWithValidation = Keys(
new KeyWithValidation(_.AltB, () => AssertCursorLeftIs(0)),
input,
new KeyWithValidation(_.AltB, () => AssertCursorLeftIs(12)),
new KeyWithValidation(_.AltB, () => AssertCursorLeftIs(7)),
new KeyWithValidation(_.AltB, () => AssertCursorLeftIs(2)),
new KeyWithValidation(_.AltB, () => AssertCursorLeftIs(0)),
_.Enter
);
var result = Test(keysWithValidation);
Assert.AreEqual(input, result);
}
[TestMethod]
public void TestEmacsForwardWord()
{
TestSetup(KeyMode.Emacs);
var keys = Keys(
new KeyWithValidation(_.AltF, () => AssertCursorLeftIs(0)),
_.A, _.A, _.A, _.Space, _.Space, _.B, _.B, _.B, _.Space, _.Space, _.C, _.C, _.C,
new KeyWithValidation(_.CtrlA, () => AssertCursorLeftIs(0)),
new KeyWithValidation(_.AltF, () => AssertCursorLeftIs(3)),
new KeyWithValidation(_.AltF, () => AssertCursorLeftIs(8)),
new KeyWithValidation(_.AltF, () => AssertCursorLeftIs(13)),
new KeyWithValidation(_.Home, CancelReadLineException.Throw));
Test(keys);
string input = "echo \"a $b c $d e\" 42";
keys = Keys(
input, _.Home, _.RightArrow, _.RightArrow, _.RightArrow, _.RightArrow, _.RightArrow,
new KeyWithValidation(_.AltF, () => AssertCursorLeftIs(10)),
new KeyWithValidation(_.AltF, () => AssertCursorLeftIs(15)),
new KeyWithValidation(_.AltF, () => AssertCursorLeftIs(18)),
new KeyWithValidation(_.Home, CancelReadLineException.Throw));
Test(keys);
}
[TestMethod]
public void TestRender()
{
TestSetup(KeyMode.Cmd);
string input = "abc -def <#123#> \"hello $name\"";
SetBufferState(input, 0);
AssertScreenIs(1,
TokenClassification.Command, "abc",
TokenClassification.None, " ",
TokenClassification.Parameter, "-def",
TokenClassification.None, " ",
TokenClassification.Comment, "<#123#>",
TokenClassification.None, " ",
TokenClassification.String, "\"hello ",
TokenClassification.Variable, "$name",
TokenClassification.String, "\"");
input = "\"$([int];\"_$(1+2)\")\"";
SetBufferState(input, input.Length);
AssertScreenIs(1,
TokenClassification.String, "\"",
TokenClassification.None, "$(",
TokenClassification.None, "[",
TokenClassification.Type, "int",
TokenClassification.None, "];",
TokenClassification.String, "\"_",
TokenClassification.None, "$(",
TokenClassification.Number, "1",
TokenClassification.Operator, "+",
TokenClassification.Number, "2",
TokenClassification.None, ")",
TokenClassification.String, "\"",
TokenClassification.None, ")",
TokenClassification.String, "\"");
input = "\"a $b c $d e\"";
SetBufferState(input, input.Length);
AssertScreenIs(1,
TokenClassification.String, "\"a ",
TokenClassification.Variable, "$b",
TokenClassification.String, " c ",
TokenClassification.Variable, "$d",
TokenClassification.String, " e\"");
var keys = Keys(
'{', _.Enter,
new KeyWithValidation(_.Backspace,
() => AssertScreenIs(2, TokenClassification.None, '{', NextLine)),
'}', _.Enter);
var result = Test(keys); Assert.AreEqual("{}", result);
string promptLine = "PS> ";
keys = Keys(
new KeyWithValidation(_.DQuote,
() => AssertScreenIs(1,
TokenClassification.None, promptLine.Substring(0, promptLine.IndexOf('>')),
Tuple.Create(ConsoleColor.Red, Console.BackgroundColor), ">",
TokenClassification.None, " ",
TokenClassification.String, "\""
)),
'"', _.Enter);
ClearScreen();
result = Test(keys, promptLine); Assert.AreEqual("\"\"", result);
}
[TestMethod]
public void TestContinuationPrompt()
{
TestSetup(KeyMode.Cmd);
const string input = "{\n}";
SetBufferState(input, input.Length);
var continuationPrompt = PSConsoleReadLine.DefaultContinuationPrompt;
var continationPrefixLength = continuationPrompt.Length;
AssertScreenIs(2,
TokenClassification.None, '{',
NextLine,
Tuple.Create(PSConsoleReadLine.DefaultContinuationPromptForegroundColor,
PSConsoleReadLine.DefaultContinuationPromptBackgroundColor),
continuationPrompt,
TokenClassification.None, '}'
);
PSConsoleReadLine.SetOptions(new SetPSReadlineOption{ ContinuationPrompt = ""});
SetBufferState(input, input.Length);
AssertScreenIs(2, TokenClassification.None, '{', NextLine, '}' );
continuationPrompt = "::::: ";
continationPrefixLength = continuationPrompt.Length;
PSConsoleReadLine.SetOptions(new SetPSReadlineOption{
ContinuationPrompt = continuationPrompt,
ContinuationPromptForegroundColor = ConsoleColor.Magenta,
ContinuationPromptBackgroundColor = ConsoleColor.DarkYellow,
});
SetBufferState(input, input.Length);
AssertScreenIs(2,
TokenClassification.None, '{',
NextLine,
Tuple.Create(ConsoleColor.Magenta, ConsoleColor.DarkYellow),
continuationPrompt,
TokenClassification.None, '}'
);
}
[TestMethod]
public void TestExchangePointAndMark()
{
TestSetup(KeyMode.Emacs,
new KeyHandler("Ctrl+Z", PSConsoleReadLine.ExchangePointAndMark));
var keys = Keys(_.A, _.B, _.C, _.D, _.E,
new KeyWithValidation(_.CtrlZ, () => AssertCursorLeftIs(0)),
_.RightArrow, _.CtrlAt, _.RightArrow,
new KeyWithValidation(_.RightArrow, () => AssertCursorLeftIs(3)),
new KeyWithValidation(_.CtrlZ, () => AssertCursorLeftIs(1)),
_.Enter);
var result = Test(keys); Assert.AreEqual("abcde", result);
// Make sure mark gets reset to 0.
keys = Keys(_.A, _.B, _.C,
new KeyWithValidation(_.CtrlZ, () => AssertCursorLeftIs(0)),
_.Enter);
result = Test(keys); Assert.AreEqual("abc", result);
}
[TestMethod]
public void TestPossibleCompletions()
{
TestSetup(KeyMode.Emacs);
ClearScreen();
// Test empty input, make sure line after the cursor is blank and cursor didn't move
var keys = Keys(
new KeyWithValidation(_.AltEquals, () =>
{
AssertCursorLeftTopIs(0, 0);
AssertScreenIs(2, NextLine);
}),
_.Enter);
Test(keys);
const string promptLine1 = "c:\\windows";
const string promptLine2 = "PS> ";
keys = Keys("psvar",
new KeyWithValidation(_.AltEquals,
() => AssertScreenIs(5,
TokenClassification.None, promptLine1,
NextLine,
promptLine2,
TokenClassification.Command, "psvar",
NextLine,
"$pssomething",
NextLine,
TokenClassification.None, promptLine1,
NextLine,
promptLine2,
TokenClassification.Command, "psvar")),
_.Enter
);
Test(keys, promptLine1 + "\n" + promptLine2);
keys = Keys("none",
new KeyWithValidation(_.AltEquals,
() => AssertScreenIs(2,
TokenClassification.Command, "none",
NextLine)),
_.Enter);
ClearScreen();
Test(keys);
using (ShimsContext.Create())
{
bool ding = false;
PSConsoleUtilities.Fakes.ShimPSConsoleReadLine.Ding =
() => ding = true;
ClearScreen();
Test(keys);
Assert.IsTrue(ding);
}
}
static private CommandCompletion MockedCompleteInput(string input, int cursor, Hashtable options, PowerShell powerShell)
{
var ctor = typeof (CommandCompletion).GetConstructor(
BindingFlags.NonPublic | BindingFlags.Instance, null,
new [] {typeof (Collection<CompletionResult>), typeof (int), typeof (int), typeof (int)}, null);
var completions = new Collection<CompletionResult>();
const int currentMatchIndex = -1;
var replacementIndex = 0;
var replacementLength = 0;
switch (input)
{
case "$t":
replacementIndex = 0;
replacementLength = 2;
completions.Add(new CompletionResult("$this"));
completions.Add(new CompletionResult("$true"));
break;
case "$tr":
replacementIndex = 0;
replacementLength = 3;
completions.Add(new CompletionResult("$true"));
break;
case "psvar":
replacementIndex = 0;
replacementLength = 5;
completions.Add(new CompletionResult("$pssomething"));
break;
case "ambig":
replacementIndex = 0;
replacementLength = 5;
completions.Add(new CompletionResult("ambiguous1"));
completions.Add(new CompletionResult("ambiguous2"));
completions.Add(new CompletionResult("ambiguous3"));
break;
case "none":
break;
}
return (CommandCompletion)ctor.Invoke(
new object[] {completions, currentMatchIndex, replacementIndex, replacementLength});
}
[TestMethod]
[ExcludeFromCodeCoverage]
public void TestUselessStuffForBetterCoverage()
{
// Useless test to just make sure coverage numbers are better, written
// in the first way I could think of that doesn't warn about doing something useless.
var options = new SetPSReadlineOption();
var useless = ((object)options.AddToHistoryHandler ?? options).GetHashCode()
+ options.EditMode.GetHashCode()
+ ((object)options.ContinuationPrompt ?? options).GetHashCode()
+ options.ContinuationPromptBackgroundColor.GetHashCode()
+ options.ContinuationPromptForegroundColor.GetHashCode()
+ options.HistoryNoDuplicates.GetHashCode()
+ options.HistorySearchCursorMovesToEnd.GetHashCode()
+ options.MaximumHistoryCount.GetHashCode()
+ options.MaximumKillRingCount.GetHashCode()
+ options.DingDuration.GetHashCode()
+ options.DingTone.GetHashCode()
+ options.BellStyle.GetHashCode()
+ options.ExtraPromptLineCount.GetHashCode()
+ options.ShowToolTips.GetHashCode();
// This assertion just avoids annoying warnings about unused variables.
Assert.AreNotEqual(Math.PI, useless);
bool exception = false;
try
{
CreateCharInfoBuffer(new object());
}
catch (ArgumentException)
{
exception = true;
}
Assert.IsTrue(exception, "CreateCharBuffer invalid arugment raised an exception");
using (ShimsContext.Create())
{
PSConsoleUtilities.Fakes.ShimPSConsoleReadLine.AllInstances.ConsoleBufferGet = x => null;
PSConsoleReadLine.SetBufferState("a", 1);
Console.CursorLeft = 0;
PSConsoleReadLine.SetBufferState("a", -1);
AssertCursorLeftIs(0);
Console.CursorLeft = 0;
PSConsoleReadLine.SetBufferState("a", 11);
AssertCursorLeftIs(1);
}
}
[TestMethod]
public void TestKeyInfoConverterSimpleCharLiteral()
{
var result = ConsoleKeyChordConverter.Convert("x");
Assert.IsNotNull(result);
Assert.AreEqual(result.Length, 1);
var key = result[0];
Assert.AreEqual(key.KeyChar, 'x');
Assert.AreEqual(key.Key, ConsoleKey.X);
Assert.AreEqual(key.Modifiers, (ConsoleModifiers)0);
}
[TestMethod]
public void TestKeyInfoConverterSimpleCharLiteralWithModifiers()
{
var result = ConsoleKeyChordConverter.Convert("alt+shift+x");
Assert.IsNotNull(result);
Assert.AreEqual(result.Length, 1);
var key = result[0];
Assert.AreEqual(key.KeyChar, 'X');
Assert.AreEqual(key.Key, ConsoleKey.X);
Assert.AreEqual(key.Modifiers, ConsoleModifiers.Shift | ConsoleModifiers.Alt);
}
[TestMethod]
public void TestKeyInfoConverterSymbolLiteral()
{
var result = ConsoleKeyChordConverter.Convert("}");
Assert.IsNotNull(result);
Assert.AreEqual(result.Length, 1);
var key = result[0];
Assert.AreEqual(key.KeyChar, '}');
Assert.AreEqual(key.Key, ConsoleKey.Oem6);
Assert.AreEqual(key.Modifiers, ConsoleModifiers.Shift);
}
[TestMethod]
public void TestKeyInfoConverterShiftedSymbolLiteral()
{
// } => shift+] / shift+oem6
var result = ConsoleKeyChordConverter.Convert("shift+]");
Assert.IsNotNull(result);
Assert.AreEqual(result.Length, 1);
var key = result[0];
Assert.AreEqual(key.KeyChar, '}');
Assert.AreEqual(key.Key, ConsoleKey.Oem6);
Assert.AreEqual(key.Modifiers, ConsoleModifiers.Shift);
}
[TestMethod]
public void TestKeyInfoConverterWellKnownConsoleKey()
{
// oem6
var result = ConsoleKeyChordConverter.Convert("shift+oem6");
Assert.IsNotNull(result);
Assert.AreEqual(result.Length, 1);
var key = result[0];
Assert.AreEqual(key.KeyChar, '}');
Assert.AreEqual(key.Key, ConsoleKey.Oem6);
Assert.AreEqual(key.Modifiers, ConsoleModifiers.Shift);
}
[TestMethod]
public void TestKeyInfoConverterSequence()
{
// oem6
var result = ConsoleKeyChordConverter.Convert("Escape,X");
Assert.IsNotNull(result);
Assert.AreEqual(result.Length, 2);
var key = result[0];
Assert.AreEqual(key.KeyChar, (char)27);
Assert.AreEqual(key.Key, ConsoleKey.Escape);
Assert.AreEqual(key.Modifiers, (ConsoleModifiers)0);
key = result[1];
Assert.AreEqual(key.KeyChar, 'x');
Assert.AreEqual(key.Key, ConsoleKey.X);
Assert.AreEqual(key.Modifiers, (ConsoleModifiers)0);
}
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void TestKeyInfoConverterInvalidKey()
{
var result = ConsoleKeyChordConverter.Convert("escrape");
}
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void TestKeyInfoConverterInvalidModifierTypo()
{
var result = ConsoleKeyChordConverter.Convert("alt+shuft+x");
}
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void TestKeyInfoConverterInvalidModifierInapplicable()
{
var result = ConsoleKeyChordConverter.Convert("shift+}");
}
[TestMethod]
[ExpectedException(typeof (ArgumentException))]
public void TestKeyInfoConverterInvalidSubsequence1()
{
var result = ConsoleKeyChordConverter.Convert("x,");
}
[TestMethod]
[ExpectedException(typeof (ArgumentException))]
public void TestKeyInfoConverterInvalidSubsequence2()
{
var result = ConsoleKeyChordConverter.Convert(",x");
}
}
}