Merge pull request 244 from dev/host into develop
Merge dev/host to develop
This commit is contained in:
commit
7a77539b50
31 changed files with 172 additions and 613 deletions
12
Makefile
12
Makefile
|
@ -36,14 +36,14 @@ bootstrap: tools/nuget.exe
|
|||
|
||||
# run targets
|
||||
|
||||
export POWERSHELL=env LD_LIBRARY_PATH=$(MONAD)/lib:$(PSLIB) PSMODULEPATH=$(PSLIB)/Modules $(MONAD)/bin/powershell
|
||||
export POWERSHELL_SIMPLE=$(POWERSHELL) $(PSLIB)/powershell-simple.exe
|
||||
export POWERSHELL_HOST=env TEMP=/tmp LD_LIBRARY_PATH=$(LD_LIBRARY_PATH):$(MONAD)/lib:$(PSLIB) PSMODULEPATH=$(PSLIB)/Modules $(MONAD)/bin/powershell
|
||||
export POWERSHELL=$(POWERSHELL_HOST) $(PSLIB)/powershell.exe
|
||||
|
||||
demo:
|
||||
$(POWERSHELL_SIMPLE) '"a","b","c","a","a" | Select-Object -Unique'
|
||||
$(POWERSHELL) '"a","b","c","a","a" | Select-Object -Unique'
|
||||
|
||||
shell:
|
||||
TEMP=/tmp $(POWERSHELL) $(PSLIB)/powershell-run.exe
|
||||
$(POWERSHELL)
|
||||
|
||||
# tests
|
||||
|
||||
|
@ -59,12 +59,12 @@ test-hashbang:
|
|||
## - we cd because some tests rely on the current working directory
|
||||
PESTER=$(MONAD)/src/pester-tests
|
||||
test-pester:
|
||||
$(POWERSHELL_SIMPLE) '$$env:TEMP="/tmp"; invoke-pester $(PESTER) -OutputFile $(MONAD)/pester-tests.xml -OutputFormat NUnitXml'
|
||||
$(POWERSHELL) 'invoke-pester $(PESTER) -OutputFile $(MONAD)/pester-tests.xml -OutputFormat NUnitXml'
|
||||
|
||||
## Pester self-tests
|
||||
## - results in pester-self-tests.xml
|
||||
test-pester-self:
|
||||
$(POWERSHELL_SIMPLE) 'cd $(PSLIB)/Modules/Pester/Functions; $$env:TEMP="/tmp"; invoke-pester -OutputFile $(MONAD)/pester-self-tests.xml -OutputFormat NUnitXml'
|
||||
$(POWERSHELL) 'cd $(PSLIB)/Modules/Pester/Functions; $$env:TEMP="/tmp"; invoke-pester -OutputFile $(MONAD)/pester-self-tests.xml -OutputFormat NUnitXml'
|
||||
|
||||
## tracing
|
||||
## - use PAL_DBG_CHANNELS="+LOADER.TRACE" to enable CoreCLR tracing
|
||||
|
|
|
@ -1,15 +1,20 @@
|
|||
# docker run magrathea without tty
|
||||
# docker run magrathea with a non-interactive tty
|
||||
monad-run()
|
||||
{
|
||||
monad-docker-run "--attach STDOUT --attach STDERR" $*
|
||||
monad-docker-run "--tty" $*
|
||||
}
|
||||
|
||||
# docker run magrathea with interactive tty
|
||||
monad-tty()
|
||||
monad-it()
|
||||
{
|
||||
monad-docker-run "--interactive --tty" $*
|
||||
}
|
||||
|
||||
monad-attach()
|
||||
{
|
||||
monad-docker-run "--attach STDOUT --attach STDERR" $*
|
||||
}
|
||||
|
||||
# runs ephemeral andschwa/magrathea docker container with local
|
||||
# directory mounted and workdir set to /opt
|
||||
monad-docker-run()
|
||||
|
|
|
@ -7,6 +7,7 @@ using System.Reflection;
|
|||
[assembly:InternalsVisibleTo("Microsoft.PowerShell.Security")]
|
||||
[assembly:InternalsVisibleTo("Microsoft.PowerShell.CoreCLR.AssemblyLoadContext")]
|
||||
[assembly:InternalsVisibleTo("PowerShell.Linux.Test")]
|
||||
[assembly:InternalsVisibleTo("powershell")]
|
||||
[assembly:AssemblyFileVersionAttribute("1.0.0.0")]
|
||||
[assembly:AssemblyVersion("1.0.0.0")]
|
||||
|
||||
|
|
15
src/host/PSL_profile.ps1
Normal file
15
src/host/PSL_profile.ps1
Normal file
|
@ -0,0 +1,15 @@
|
|||
(get-psprovider 'FileSystem').Home = $env:HOME
|
||||
|
||||
function prompt
|
||||
{
|
||||
"PSL " + $(get-location) + "> "
|
||||
}
|
||||
|
||||
& {
|
||||
for ($i = 0; $i -lt 26; $i++)
|
||||
{
|
||||
$funcname = ([System.Char]($i+65)) + ':'
|
||||
$str = "function global:$funcname { set-location $funcname } "
|
||||
invoke-expression $str
|
||||
}
|
||||
}
|
17
src/host/host.mk
Normal file
17
src/host/host.mk
Normal file
|
@ -0,0 +1,17 @@
|
|||
# This is the makefile for all kinds of powershell hosts
|
||||
#
|
||||
# Currently there is powershell-run.exe, which is a very generic interactive and
|
||||
# non-interactive host
|
||||
|
||||
POWERSHELL_RUN_FOLDER=$(MONAD)/src/host
|
||||
POWERSHELL_RUN_SRCS=$(addprefix $(POWERSHELL_RUN_FOLDER)/, main.cs host.cs ui.cs rawui.cs readline.cs powershell.assembly-info.cs)
|
||||
|
||||
# direct dependencies to be linked in
|
||||
POWERSHELL_RUN_DEPS=$(addprefix $(PSLIB)/, System.Management.Automation.dll Microsoft.PowerShell.Commands.Management.dll $(ASSEMBLY_LOAD_CONTEXT_TARGET))
|
||||
POWERSHELL_RUN_REFS=$(addprefix -r:, $(POWERSHELL_RUN_DEPS))
|
||||
|
||||
$(PSLIB)/PSL_profile.ps1:
|
||||
cp -f $(POWERSHELL_RUN_FOLDER)/$(notdir $@) $@
|
||||
|
||||
$(PSLIB)/powershell.exe: $(POWERSHELL_RUN_SRCS) $(POWERSHELL_RUN_DEPS) $(PSLIB)/PSL_profile.ps1
|
||||
$(CSC) -out:$@ -noconfig -nostdlib -target:exe $(POWERSHELL_RUN_REFS) $(COREREF) $(POWERSHELL_RUN_SRCS)
|
|
@ -74,55 +74,38 @@ namespace Microsoft.Samples.PowerShell.Host
|
|||
set { this.exitCode = value; }
|
||||
}
|
||||
|
||||
// this is the unmanaged main entry point used by the CoreCLR host
|
||||
public static int UnmanagedMain(int argc, [MarshalAs(UnmanagedType.LPArray,ArraySubType=UnmanagedType.LPStr,SizeParamIndex=0)] String[] argv)
|
||||
{
|
||||
List<String> allArgs = new List<String>();
|
||||
|
||||
for (int i = 0; i < argc; ++i)
|
||||
{
|
||||
allArgs.Add(argv[i]);
|
||||
}
|
||||
|
||||
ManagedMain(allArgs.ToArray());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates and initiates the listener instance.
|
||||
/// </summary>
|
||||
/// <param name="args">This parameter is not used.</param>
|
||||
private static void Main(string[] args)
|
||||
{
|
||||
ManagedMain(args);
|
||||
}
|
||||
|
||||
private static void ManagedMain(string[] args)
|
||||
{
|
||||
|
||||
String initialScript = null;
|
||||
// Custom argument parsing
|
||||
string initialScript = null;
|
||||
if (args.Length > 0)
|
||||
{
|
||||
for (int i = 0; i < args.Length; ++i)
|
||||
{
|
||||
string arg = args[i];
|
||||
bool hasNext = (i+1)<args.Length;
|
||||
string nextArg = hasNext ? args[i+1] : "";
|
||||
bool hasNext = (i+1) < args.Length;
|
||||
string nextArg = hasNext ? args[i+1] : string.Empty;
|
||||
|
||||
if (hasNext && arg == "--file")
|
||||
{
|
||||
initialScript = File.ReadAllText(nextArg);
|
||||
initialScript = Path.GetFullPath(nextArg);
|
||||
++i;
|
||||
}
|
||||
else if (arg.EndsWith(".ps1"))
|
||||
{
|
||||
initialScript = Path.GetFullPath(arg);
|
||||
}
|
||||
else if (hasNext && arg == "--working-dir")
|
||||
{
|
||||
Directory.SetCurrentDirectory(nextArg);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
if ( String.IsNullOrEmpty(initialScript) && args.Length > 0 )
|
||||
if (string.IsNullOrEmpty(initialScript))
|
||||
{
|
||||
initialScript = string.Join(" ", args);
|
||||
}
|
||||
|
@ -158,12 +141,44 @@ namespace Microsoft.Samples.PowerShell.Host
|
|||
// only the default snap-ins will be available.
|
||||
this.myHost = new MyHost(this);
|
||||
InitialSessionState iss = InitialSessionState.CreateDefault2();
|
||||
this.myRunSpace = RunspaceFactory.CreateRunspace(this.myHost,iss);
|
||||
this.myRunSpace = RunspaceFactory.CreateRunspace(this.myHost, iss);
|
||||
this.myRunSpace.Open();
|
||||
|
||||
// Create a PowerShell object to run the commands used to create
|
||||
// $profile and load the profiles.
|
||||
lock (this.instanceLock)
|
||||
{
|
||||
this.currentPowerShell = PowerShell.Create();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
this.currentPowerShell.Runspace = this.myRunSpace;
|
||||
|
||||
PSCommand[] profileCommands = HostUtilities.GetProfileCommands("PSL");
|
||||
foreach (PSCommand command in profileCommands)
|
||||
{
|
||||
this.currentPowerShell.Commands = command;
|
||||
this.currentPowerShell.Invoke();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Dispose the PowerShell object and set currentPowerShell
|
||||
// to null. It is locked because currentPowerShell may be
|
||||
// accessed by the ctrl-C handler.
|
||||
lock (this.instanceLock)
|
||||
{
|
||||
this.currentPowerShell.Dispose();
|
||||
this.currentPowerShell = null;
|
||||
}
|
||||
}
|
||||
|
||||
// run the initial script
|
||||
if (initialScript != null)
|
||||
executeHelper(initialScript,null);
|
||||
{
|
||||
executeHelper(initialScript, null);
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the prompt equal to the output of the prompt function
|
||||
|
@ -203,7 +218,7 @@ namespace Microsoft.Samples.PowerShell.Host
|
|||
private void executeHelper(string cmd, object input)
|
||||
{
|
||||
// Ignore empty command lines.
|
||||
if (String.IsNullOrEmpty(cmd))
|
||||
if (string.IsNullOrEmpty(cmd))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -223,8 +238,6 @@ namespace Microsoft.Samples.PowerShell.Host
|
|||
{
|
||||
this.currentPowerShell.Runspace = this.myRunSpace;
|
||||
|
||||
// TODO: Find out where this is set in the Monad host code and set all defaults that way
|
||||
this.currentPowerShell.AddScript(string.Format("(Get-PSProvider 'FileSystem').Home = '{0}'",Environment.GetEnvironmentVariable("HOME")));
|
||||
this.currentPowerShell.AddScript(cmd);
|
||||
|
||||
// Add the default outputter to the end of the pipe and then call the
|
||||
|
@ -387,12 +400,10 @@ namespace Microsoft.Samples.PowerShell.Host
|
|||
// the user calling "exit".
|
||||
while (!this.ShouldExit)
|
||||
{
|
||||
string prompt;
|
||||
prompt = Prompt(this.myHost.Runspace);
|
||||
string prompt = Prompt(this.myHost.Runspace);
|
||||
|
||||
this.myHost.UI.Write(ConsoleColor.White, ConsoleColor.Black, prompt);
|
||||
// string cmd = this.consoleReadLine.Read();
|
||||
string cmd = Console.ReadLine();
|
||||
string cmd = this.myHost.UI.ReadLine();
|
||||
this.Execute(cmd);
|
||||
}
|
||||
|
|
@ -14,13 +14,14 @@ namespace Microsoft.Samples.PowerShell.Host
|
|||
{
|
||||
// this is all from https://msdn.microsoft.com/en-us/library/ee706570%28v=vs.85%29.aspx
|
||||
|
||||
internal class MyRawUserInterface : PSHostRawUserInterface
|
||||
internal class MyRawUserInterface : PSHostRawUserInterface
|
||||
{
|
||||
// this class provides features otherwise not available through .net
|
||||
internal class Native
|
||||
{
|
||||
[DllImport("libpsnative")]
|
||||
internal static extern int GetTerminalWidth();
|
||||
|
||||
[DllImport("libpsnative")]
|
||||
internal static extern int GetTerminalHeight();
|
||||
}
|
||||
|
@ -55,9 +56,9 @@ namespace Microsoft.Samples.PowerShell.Host
|
|||
public override Coordinates CursorPosition
|
||||
{
|
||||
get { throw new NotImplementedException(
|
||||
"The method or operation is not implemented."); }
|
||||
"The method or operation is not implemented."); }
|
||||
set { throw new NotImplementedException(
|
||||
"The method or operation is not implemented."); }
|
||||
"The method or operation is not implemented."); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -89,8 +90,8 @@ namespace Microsoft.Samples.PowerShell.Host
|
|||
/// </summary>
|
||||
public override bool KeyAvailable
|
||||
{
|
||||
get { return false; }
|
||||
// get { return Console.KeyAvailable; }
|
||||
get { return false; }
|
||||
// get { return Console.KeyAvailable; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -102,8 +103,8 @@ namespace Microsoft.Samples.PowerShell.Host
|
|||
/// </summary>
|
||||
public override Size MaxPhysicalWindowSize
|
||||
{
|
||||
// get { return new Size(Console.LargestWindowWidth, Console.LargestWindowHeight); }
|
||||
get { return new Size(1024,768); }
|
||||
// get { return new Size(Console.LargestWindowWidth, Console.LargestWindowHeight); }
|
||||
get { return new Size(1024,768); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -114,8 +115,8 @@ namespace Microsoft.Samples.PowerShell.Host
|
|||
/// </summary>
|
||||
public override Size MaxWindowSize
|
||||
{
|
||||
// get { return new Size(Console.LargestWindowWidth, Console.LargestWindowHeight); }
|
||||
get { return new Size(1024,768); }
|
||||
// get { return new Size(Console.LargestWindowWidth, Console.LargestWindowHeight); }
|
||||
get { return new Size(1024,768); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -125,8 +126,8 @@ namespace Microsoft.Samples.PowerShell.Host
|
|||
/// </summary>
|
||||
public override Coordinates WindowPosition
|
||||
{
|
||||
// get { return new Coordinates(Console.WindowLeft, Console.WindowTop); }
|
||||
// set { Console.SetWindowPosition(value.X, value.Y); }
|
||||
// get { return new Coordinates(Console.WindowLeft, Console.WindowTop); }
|
||||
// set { Console.SetWindowPosition(value.X, value.Y); }
|
||||
get { return new Coordinates(0,0); }
|
||||
set { }
|
||||
}
|
||||
|
@ -138,8 +139,8 @@ namespace Microsoft.Samples.PowerShell.Host
|
|||
/// </summary>
|
||||
public override Size WindowSize
|
||||
{
|
||||
// get { return new Size(Console.WindowWidth, Console.WindowHeight); }
|
||||
// set { Console.SetWindowSize(value.Width, value.Height); }
|
||||
// get { return new Size(Console.WindowWidth, Console.WindowHeight); }
|
||||
// set { Console.SetWindowSize(value.Width, value.Height); }
|
||||
get { return new Size(1024,768); }
|
||||
set { }
|
||||
}
|
||||
|
@ -150,8 +151,8 @@ namespace Microsoft.Samples.PowerShell.Host
|
|||
/// </summary>
|
||||
public override string WindowTitle
|
||||
{
|
||||
// get { return Console.Title; }
|
||||
// set { Console.Title = value; }
|
||||
// get { return Console.Title; }
|
||||
// set { Console.Title = value; }
|
||||
get { return "window title"; }
|
||||
set { }
|
||||
}
|
||||
|
@ -174,7 +175,7 @@ namespace Microsoft.Samples.PowerShell.Host
|
|||
public override BufferCell[,] GetBufferContents(Rectangle rectangle)
|
||||
{
|
||||
throw new NotImplementedException(
|
||||
"The method or operation is not implemented.");
|
||||
"The method or operation is not implemented.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -190,7 +191,7 @@ namespace Microsoft.Samples.PowerShell.Host
|
|||
public override KeyInfo ReadKey(ReadKeyOptions options)
|
||||
{
|
||||
throw new NotImplementedException(
|
||||
"The method or operation is not implemented.");
|
||||
"The method or operation is not implemented.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -206,7 +207,7 @@ namespace Microsoft.Samples.PowerShell.Host
|
|||
public override void ScrollBufferContents(Rectangle source, Coordinates destination, Rectangle clip, BufferCell fill)
|
||||
{
|
||||
throw new NotImplementedException(
|
||||
"The method or operation is not implemented.");
|
||||
"The method or operation is not implemented.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -220,7 +221,7 @@ namespace Microsoft.Samples.PowerShell.Host
|
|||
BufferCell[,] contents)
|
||||
{
|
||||
throw new NotImplementedException(
|
||||
"The method or operation is not implemented.");
|
||||
"The method or operation is not implemented.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -233,9 +234,7 @@ namespace Microsoft.Samples.PowerShell.Host
|
|||
public override void SetBufferContents(Rectangle rectangle, BufferCell fill)
|
||||
{
|
||||
throw new NotImplementedException(
|
||||
"The method or operation is not implemented.");
|
||||
"The method or operation is not implemented.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -49,28 +49,28 @@ namespace Microsoft.Samples.PowerShell.Host
|
|||
public ConsoleReadLine()
|
||||
{
|
||||
this.tokenColors = new ConsoleColor[]
|
||||
{
|
||||
this.defaultColor, // Unknown
|
||||
{
|
||||
this.defaultColor, // Unknown
|
||||
ConsoleColor.Yellow, // Command
|
||||
ConsoleColor.Green, // CommandParameter
|
||||
ConsoleColor.Cyan, // CommandArgument
|
||||
ConsoleColor.Cyan, // Number
|
||||
ConsoleColor.Cyan, // String
|
||||
ConsoleColor.Green, // Variable
|
||||
this.defaultColor, // Member
|
||||
this.defaultColor, // LoopLabel
|
||||
this.defaultColor, // Member
|
||||
this.defaultColor, // LoopLabel
|
||||
ConsoleColor.DarkYellow, // Attribute
|
||||
ConsoleColor.DarkYellow, // Type
|
||||
ConsoleColor.DarkCyan, // Operator
|
||||
this.defaultColor, // GroupStart
|
||||
this.defaultColor, // GroupEnd
|
||||
this.defaultColor, // GroupStart
|
||||
this.defaultColor, // GroupEnd
|
||||
ConsoleColor.Magenta, // Keyword
|
||||
ConsoleColor.Red, // Comment
|
||||
ConsoleColor.DarkCyan, // StatementSeparator
|
||||
this.defaultColor, // NewLine
|
||||
this.defaultColor, // LineContinuation
|
||||
this.defaultColor, // Position
|
||||
};
|
||||
this.defaultColor, // NewLine
|
||||
this.defaultColor, // LineContinuation
|
||||
this.defaultColor, // Position
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
|
@ -1 +1 @@
|
|||
Subproject commit f6bd69cc07c0d564379c684654a3c37b0fbfdaad
|
||||
Subproject commit 82cc60caa6bb6fd5ece013763669d8e1c91809f6
|
|
@ -1 +1 @@
|
|||
Subproject commit 2b2ea2820b2dfce1742e4e81023dde9c324f9fa9
|
||||
Subproject commit 80e99a447f433f2e8f91a567d8171d5207a88dc3
|
|
@ -1 +1 @@
|
|||
Subproject commit 102f6163a17afec6e27107ec0fdfec5fd458c706
|
||||
Subproject commit 99485dea3ecedcaed32a4e31e55cdc2073504511
|
|
@ -1,34 +1,34 @@
|
|||
Describe "Format-List" {
|
||||
BeforeEach {
|
||||
$input = New-Object PSObject
|
||||
Add-Member -InputObject $input -MemberType NoteProperty -Name testName -Value testValue
|
||||
$in = New-Object PSObject
|
||||
Add-Member -InputObject $in -MemberType NoteProperty -Name testName -Value testValue
|
||||
}
|
||||
|
||||
It "Should call format list without error" {
|
||||
{ $input | Format-List } | Should Not Throw
|
||||
{ $input | Format-List } | Should Not BeNullOrEmpty
|
||||
{ $in | Format-List } | Should Not Throw
|
||||
{ $in | Format-List } | Should Not BeNullOrEmpty
|
||||
}
|
||||
|
||||
It "Should be able to call the alias" {
|
||||
{ $input | fl } | Should Not Throw
|
||||
{ $input | fl } | Should Not BeNullOrEmpty
|
||||
{ $in | fl } | Should Not Throw
|
||||
{ $in | fl } | Should Not BeNullOrEmpty
|
||||
}
|
||||
|
||||
It "Should have the same output whether choosing alias or not" {
|
||||
$expected = $input | Format-List | Out-String
|
||||
$actual = $input | fl | Out-String
|
||||
$expected = $in | Format-List | Out-String
|
||||
$actual = $in | fl | Out-String
|
||||
|
||||
$actual | Should Be $expected
|
||||
}
|
||||
|
||||
It "Should produce the expected output" {
|
||||
$expected = "`n`ntestName : testValue`n`n`n`n"
|
||||
$input = New-Object PSObject
|
||||
Add-Member -InputObject $input -MemberType NoteProperty -Name testName -Value testValue
|
||||
$in = New-Object PSObject
|
||||
Add-Member -InputObject $in -MemberType NoteProperty -Name testName -Value testValue
|
||||
|
||||
$input | Format-List | Should Not BeNullOrEmpty
|
||||
$input | Format-List | Out-String | Should Not BeNullOrEmpty
|
||||
$input | Format-List | Out-String | Should Be $expected
|
||||
$in | Format-List | Should Not BeNullOrEmpty
|
||||
$in | Format-List | Out-String | Should Not BeNullOrEmpty
|
||||
$in | Format-List | Out-String | Should Be $expected
|
||||
}
|
||||
|
||||
It "Should be able to call a property of the piped input" {
|
||||
|
@ -64,7 +64,7 @@ Describe "Format-List" {
|
|||
}
|
||||
|
||||
It "Should be able to take input without piping objects to it" {
|
||||
$output = { Format-List -InputObject $input }
|
||||
$output = { Format-List -InputObject $in }
|
||||
|
||||
$output | Should Not Throw
|
||||
$output | Should Not BeNullOrEmpty
|
||||
|
|
|
@ -49,18 +49,18 @@
|
|||
}
|
||||
|
||||
It "Should be able to set the value of a variable by piped input" {
|
||||
$input = "value"
|
||||
$in = "value"
|
||||
|
||||
$input | New-Variable -Name var1
|
||||
$in | New-Variable -Name var1
|
||||
|
||||
$var1 | Should Be $input
|
||||
$var1 | Should Be $in
|
||||
|
||||
}
|
||||
|
||||
It "Should be able to pipe object properties to output using the PassThru switch" {
|
||||
$input = Set-Variable -Name testVar -Value "test" -Description "test description" -PassThru
|
||||
$in = Set-Variable -Name testVar -Value "test" -Description "test description" -PassThru
|
||||
|
||||
$output = $input | Format-List -Property Description | Out-String
|
||||
$output = $in | Format-List -Property Description | Out-String
|
||||
|
||||
$output | Should Be "`n`nDescription : test description`n`n`n`n"
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
Describe "Out-File" {
|
||||
$expectedContent = "some test text"
|
||||
$inputObject = New-Object psobject -Property @{text=$expectedContent}
|
||||
$inObject = New-Object psobject -Property @{text=$expectedContent}
|
||||
$testfile = "/tmp/outfileTest.txt"
|
||||
|
||||
AfterEach {
|
||||
|
@ -28,17 +28,17 @@
|
|||
}
|
||||
|
||||
It "Should be able to accept object input" {
|
||||
{ $inputObject | Out-File -FilePath $testfile } | Should Not Throw
|
||||
{ $inObject | Out-File -FilePath $testfile } | Should Not Throw
|
||||
|
||||
{ Out-File -FilePath $testfile -InputObject $inputObject } | Should Not Throw
|
||||
{ Out-File -FilePath $testfile -InputObject $inObject } | Should Not Throw
|
||||
}
|
||||
|
||||
It "Should not overwrite when the noclobber switch is used" {
|
||||
|
||||
Out-File -FilePath $testfile -InputObject $inputObject
|
||||
Out-File -FilePath $testfile -InputObject $inObject
|
||||
|
||||
{ Out-File -FilePath $testfile -InputObject $inputObject -NoClobber -ErrorAction SilentlyContinue } | Should Throw "already exists."
|
||||
{ Out-File -FilePath $testfile -InputObject $inputObject -NoOverWrite -ErrorAction SilentlyContinue } | Should Throw "already exists."
|
||||
{ Out-File -FilePath $testfile -InputObject $inObject -NoClobber -ErrorAction SilentlyContinue } | Should Throw "already exists."
|
||||
{ Out-File -FilePath $testfile -InputObject $inObject -NoOverWrite -ErrorAction SilentlyContinue } | Should Throw "already exists."
|
||||
|
||||
$actual = Get-Content $testfile
|
||||
|
||||
|
@ -49,8 +49,8 @@
|
|||
}
|
||||
|
||||
It "Should Append a new line when the append switch is used" {
|
||||
{ Out-File -FilePath $testfile -InputObject $inputObject } | Should Not Throw
|
||||
{ Out-File -FilePath $testfile -InputObject $inputObject -Append } | Should Not Throw
|
||||
{ Out-File -FilePath $testfile -InputObject $inObject } | Should Not Throw
|
||||
{ Out-File -FilePath $testfile -InputObject $inObject -Append } | Should Not Throw
|
||||
|
||||
$actual = Get-Content $testfile
|
||||
|
||||
|
@ -71,7 +71,7 @@
|
|||
|
||||
It "Should limit each line to the specified number of characters when the width switch is used on objects" {
|
||||
|
||||
Out-File -FilePath $testfile -Width 10 -InputObject $inputObject
|
||||
Out-File -FilePath $testfile -Width 10 -InputObject $inObject
|
||||
|
||||
$actual = Get-Content $testfile
|
||||
|
||||
|
@ -84,11 +84,11 @@
|
|||
|
||||
It "Should allow the cmdlet to overwrite an existing read-only file" {
|
||||
# create a read-only text file
|
||||
{ Out-File -FilePath $testfile -InputObject $inputObject } | Should Not Throw
|
||||
{ Out-File -FilePath $testfile -InputObject $inObject } | Should Not Throw
|
||||
Set-ItemProperty -Path $testfile -Name IsReadOnly -Value $true
|
||||
|
||||
# write information to the RO file
|
||||
{ Out-File -FilePath $testfile -InputObject $inputObject -Append -Force } | Should Not Throw
|
||||
{ Out-File -FilePath $testfile -InputObject $inObject -Append -Force } | Should Not Throw
|
||||
|
||||
$actual = Get-Content $testfile
|
||||
|
||||
|
|
|
@ -48,9 +48,9 @@
|
|||
}
|
||||
|
||||
It "Should be able to pipe object properties to output using the PassThru switch" {
|
||||
$input = Set-Variable -Name testVar -Value "test" -Description "test description" -PassThru
|
||||
$in = Set-Variable -Name testVar -Value "test" -Description "test description" -PassThru
|
||||
|
||||
$output = $input | Format-List -Property Description | Out-String
|
||||
$output = $in | Format-List -Property Description | Out-String
|
||||
|
||||
# This will cause errors running these tests in windows
|
||||
$output | Should Be "`n`nDescription : test description`n`n`n`n"
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
using System.Reflection;
|
||||
[assembly:AssemblyFileVersionAttribute("1.0.0.0")]
|
||||
[assembly:AssemblyVersion("1.0.0.0")]
|
|
@ -1,497 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Management.Automation;
|
||||
using System.Management.Automation.Runspaces;
|
||||
using System.Management.Automation.Host;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.IO;
|
||||
|
||||
namespace ps_hello_world
|
||||
{
|
||||
// this is all from https://msdn.microsoft.com/en-us/library/ee706570%28v=vs.85%29.aspx
|
||||
|
||||
internal class MyRawUserInterface : PSHostRawUserInterface
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the background color of the displayed text.
|
||||
/// This maps to the corresponding Console.Background property.
|
||||
/// </summary>
|
||||
public override ConsoleColor BackgroundColor
|
||||
{
|
||||
get { return Console.BackgroundColor; }
|
||||
set { Console.BackgroundColor = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the size of the host buffer. In this example the
|
||||
/// buffer size is adapted from the Console buffer size members.
|
||||
/// </summary>
|
||||
public override Size BufferSize
|
||||
{
|
||||
get { return new Size(200,500); }
|
||||
set { }
|
||||
//get { return new Size(Console.BufferWidth, Console.BufferHeight); }
|
||||
//set { Console.SetBufferSize(value.Width, value.Height); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the cursor position. In this example this
|
||||
/// functionality is not needed so the property throws a
|
||||
/// NotImplementException exception.
|
||||
/// </summary>
|
||||
public override Coordinates CursorPosition
|
||||
{
|
||||
get { throw new NotImplementedException(
|
||||
"The method or operation is not implemented."); }
|
||||
set { throw new NotImplementedException(
|
||||
"The method or operation is not implemented."); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the size of the displayed cursor. In this example
|
||||
/// the cursor size is taken directly from the Console.CursorSize
|
||||
/// property.
|
||||
/// </summary>
|
||||
public override int CursorSize
|
||||
{
|
||||
get { return 12; }
|
||||
set { }
|
||||
//get { return Console.CursorSize; }
|
||||
//set { Console.CursorSize = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the foreground color of the displayed text.
|
||||
/// This maps to the corresponding Console.ForgroundColor property.
|
||||
/// </summary>
|
||||
public override ConsoleColor ForegroundColor
|
||||
{
|
||||
get { return Console.ForegroundColor; }
|
||||
set { Console.ForegroundColor = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the user has pressed a key. This maps
|
||||
/// to the corresponding Console.KeyAvailable property.
|
||||
/// </summary>
|
||||
public override bool KeyAvailable
|
||||
{
|
||||
get { return false; }
|
||||
// get { return Console.KeyAvailable; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the dimensions of the largest window that could be
|
||||
/// rendered in the current display, if the buffer was at the least
|
||||
/// that large. This example uses the Console.LargestWindowWidth and
|
||||
/// Console.LargestWindowHeight properties to determine the returned
|
||||
/// value of this property.
|
||||
/// </summary>
|
||||
public override Size MaxPhysicalWindowSize
|
||||
{
|
||||
// get { return new Size(Console.LargestWindowWidth, Console.LargestWindowHeight); }
|
||||
get { return new Size(1024,768); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the dimentions of the largest window size that can be
|
||||
/// displayed. This example uses the Console.LargestWindowWidth and
|
||||
/// console.LargestWindowHeight properties to determine the returned
|
||||
/// value of this property.
|
||||
/// </summary>
|
||||
public override Size MaxWindowSize
|
||||
{
|
||||
// get { return new Size(Console.LargestWindowWidth, Console.LargestWindowHeight); }
|
||||
get { return new Size(1024,768); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the position of the displayed window. This example
|
||||
/// uses the Console window position APIs to determine the returned
|
||||
/// value of this property.
|
||||
/// </summary>
|
||||
public override Coordinates WindowPosition
|
||||
{
|
||||
// get { return new Coordinates(Console.WindowLeft, Console.WindowTop); }
|
||||
// set { Console.SetWindowPosition(value.X, value.Y); }
|
||||
get { return new Coordinates(0,0); }
|
||||
set { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the size of the displayed window. This example
|
||||
/// uses the corresponding Console window size APIs to determine the
|
||||
/// returned value of this property.
|
||||
/// </summary>
|
||||
public override Size WindowSize
|
||||
{
|
||||
// get { return new Size(Console.WindowWidth, Console.WindowHeight); }
|
||||
// set { Console.SetWindowSize(value.Width, value.Height); }
|
||||
get { return new Size(1024,768); }
|
||||
set { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the title of the displayed window. The example
|
||||
/// maps the Console.Title property to the value of this property.
|
||||
/// </summary>
|
||||
public override string WindowTitle
|
||||
{
|
||||
// get { return Console.Title; }
|
||||
// set { Console.Title = value; }
|
||||
get { return "window title"; }
|
||||
set { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This API resets the input buffer. In this example this
|
||||
/// functionality is not needed so the method returns nothing.
|
||||
/// </summary>
|
||||
public override void FlushInputBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This API returns a rectangular region of the screen buffer. In
|
||||
/// this example this functionality is not needed so the method throws
|
||||
/// a NotImplementException exception.
|
||||
/// </summary>
|
||||
/// <param name="rectangle">Defines the size of the rectangle.</param>
|
||||
/// <returns>Throws a NotImplementedException exception.</returns>
|
||||
public override BufferCell[,] GetBufferContents(Rectangle rectangle)
|
||||
{
|
||||
throw new NotImplementedException(
|
||||
"The method or operation is not implemented.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This API reads a pressed, released, or pressed and released keystroke
|
||||
/// from the keyboard device, blocking processing until a keystroke is
|
||||
/// typed that matches the specified keystroke options. In this example
|
||||
/// this functionality is not needed so the method throws a
|
||||
/// NotImplementException exception.
|
||||
/// </summary>
|
||||
/// <param name="options">Options, such as IncludeKeyDown, used when
|
||||
/// reading the keyboard.</param>
|
||||
/// <returns>Throws a NotImplementedException exception.</returns>
|
||||
public override KeyInfo ReadKey(ReadKeyOptions options)
|
||||
{
|
||||
throw new NotImplementedException(
|
||||
"The method or operation is not implemented.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This API crops a region of the screen buffer. In this example
|
||||
/// this functionality is not needed so the method throws a
|
||||
/// NotImplementException exception.
|
||||
/// </summary>
|
||||
/// <param name="source">The region of the screen to be scrolled.</param>
|
||||
/// <param name="destination">The region of the screen to receive the
|
||||
/// source region contents.</param>
|
||||
/// <param name="clip">The region of the screen to include in the operation.</param>
|
||||
/// <param name="fill">The character and attributes to be used to fill all cell.</param>
|
||||
public override void ScrollBufferContents(Rectangle source, Coordinates destination, Rectangle clip, BufferCell fill)
|
||||
{
|
||||
throw new NotImplementedException(
|
||||
"The method or operation is not implemented.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method copies an array of buffer cells into the screen buffer
|
||||
/// at a specified location. In this example this functionality is
|
||||
/// not needed so the method throws a NotImplementedException exception.
|
||||
/// </summary>
|
||||
/// <param name="origin">The parameter is not used.</param>
|
||||
/// <param name="contents">The parameter is not used.</param>
|
||||
public override void SetBufferContents(Coordinates origin,
|
||||
BufferCell[,] contents)
|
||||
{
|
||||
throw new NotImplementedException(
|
||||
"The method or operation is not implemented.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method copies a given character, foreground color, and background
|
||||
/// color to a region of the screen buffer. In this example this
|
||||
/// functionality is not needed so the method throws a
|
||||
/// NotImplementException exception./// </summary>
|
||||
/// <param name="rectangle">Defines the area to be filled. </param>
|
||||
/// <param name="fill">Defines the fill character.</param>
|
||||
public override void SetBufferContents(Rectangle rectangle, BufferCell fill)
|
||||
{
|
||||
throw new NotImplementedException(
|
||||
"The method or operation is not implemented.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal class MyHostUI : PSHostUserInterface
|
||||
{
|
||||
private MyRawUserInterface myRawUi = new MyRawUserInterface();
|
||||
|
||||
public override PSHostRawUserInterface RawUI
|
||||
{
|
||||
get { return this.myRawUi; }
|
||||
}
|
||||
|
||||
public override Dictionary<string, PSObject> Prompt(
|
||||
string caption,
|
||||
string message,
|
||||
System.Collections.ObjectModel.Collection<FieldDescription> descriptions)
|
||||
{
|
||||
throw new NotImplementedException(
|
||||
"The method or operation is not implemented.");
|
||||
}
|
||||
|
||||
public override int PromptForChoice(string caption, string message, System.Collections.ObjectModel.Collection<ChoiceDescription> choices, int defaultChoice)
|
||||
{
|
||||
throw new NotImplementedException("The method or operation is not implemented.");
|
||||
}
|
||||
|
||||
public override PSCredential PromptForCredential(
|
||||
string caption,
|
||||
string message,
|
||||
string userName,
|
||||
string targetName)
|
||||
{
|
||||
throw new NotImplementedException("The method or operation is not implemented.");
|
||||
}
|
||||
|
||||
public override PSCredential PromptForCredential(
|
||||
string caption,
|
||||
string message,
|
||||
string userName,
|
||||
string targetName,
|
||||
PSCredentialTypes allowedCredentialTypes,
|
||||
PSCredentialUIOptions options)
|
||||
{
|
||||
throw new NotImplementedException("The method or operation is not implemented.");
|
||||
}
|
||||
|
||||
public override string ReadLine()
|
||||
{
|
||||
return Console.ReadLine();
|
||||
}
|
||||
|
||||
public override System.Security.SecureString ReadLineAsSecureString()
|
||||
{
|
||||
throw new NotImplementedException("The method or operation is not implemented.");
|
||||
}
|
||||
|
||||
public override void Write(string value)
|
||||
{
|
||||
Console.BackgroundColor = ConsoleColor.Black;
|
||||
Console.Write(value);
|
||||
Console.ResetColor();
|
||||
}
|
||||
|
||||
public override void Write(
|
||||
ConsoleColor foregroundColor,
|
||||
ConsoleColor backgroundColor,
|
||||
string value)
|
||||
{
|
||||
// Colors are ignored.
|
||||
Console.ForegroundColor = foregroundColor;
|
||||
Console.BackgroundColor = backgroundColor;
|
||||
Console.Write(value);
|
||||
Console.ResetColor();
|
||||
}
|
||||
|
||||
public override void WriteDebugLine(string message)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||
Console.Write(String.Format(
|
||||
CultureInfo.CurrentCulture,
|
||||
"DEBUG: {0}",
|
||||
message));
|
||||
Console.ResetColor();
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
public override void WriteErrorLine(string value)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.Write(String.Format(
|
||||
CultureInfo.CurrentCulture,
|
||||
"ERROR: {0}",
|
||||
value));
|
||||
Console.ResetColor();
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
public override void WriteLine()
|
||||
{
|
||||
System.Console.WriteLine();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public override void WriteLine(string value)
|
||||
{
|
||||
Write(value);
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
public override void WriteLine(ConsoleColor foregroundColor, ConsoleColor backgroundColor, string value)
|
||||
{
|
||||
Write(foregroundColor,backgroundColor,value);
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
public override void WriteProgress(long sourceId, ProgressRecord record)
|
||||
{
|
||||
}
|
||||
|
||||
public override void WriteVerboseLine(string message)
|
||||
{
|
||||
Console.BackgroundColor = ConsoleColor.Gray;
|
||||
Console.WriteLine(String.Format(CultureInfo.CurrentCulture, "VERBOSE: {0}", message));
|
||||
Console.ResetColor();
|
||||
}
|
||||
|
||||
public override void WriteWarningLine(string message)
|
||||
{
|
||||
Console.BackgroundColor = ConsoleColor.Yellow;
|
||||
Console.WriteLine(String.Format(CultureInfo.CurrentCulture, "WARNING: {0}", message));
|
||||
Console.ResetColor();
|
||||
}
|
||||
}
|
||||
|
||||
internal class MyHost : PSHost
|
||||
{
|
||||
private Program program;
|
||||
private CultureInfo originalCultureInfo = new CultureInfo("en-US");
|
||||
private CultureInfo originalUICultureInfo = new CultureInfo("en-US");
|
||||
private Guid myId = Guid.NewGuid();
|
||||
|
||||
public MyHost(Program program)
|
||||
{
|
||||
this.program = program;
|
||||
}
|
||||
|
||||
private MyHostUI myHostUI = new MyHostUI();
|
||||
|
||||
public override System.Globalization.CultureInfo CurrentCulture
|
||||
{
|
||||
get { return this.originalCultureInfo; }
|
||||
}
|
||||
|
||||
public override System.Globalization.CultureInfo CurrentUICulture
|
||||
{
|
||||
get { return this.originalUICultureInfo; }
|
||||
}
|
||||
|
||||
public override Guid InstanceId
|
||||
{
|
||||
get { return myId; }
|
||||
}
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get { return "MyHost"; }
|
||||
}
|
||||
|
||||
public override PSHostUserInterface UI
|
||||
{
|
||||
get { return myHostUI; }
|
||||
}
|
||||
|
||||
public override Version Version
|
||||
{
|
||||
get { return new Version(0,0,0,0); }
|
||||
}
|
||||
|
||||
public override void EnterNestedPrompt()
|
||||
{
|
||||
throw new NotImplementedException("EnterNestedPrompt not implemented");
|
||||
}
|
||||
|
||||
public override void ExitNestedPrompt()
|
||||
{
|
||||
throw new NotImplementedException("ExitNestedPrompt not implemented");
|
||||
}
|
||||
|
||||
public override void NotifyBeginApplication()
|
||||
{
|
||||
Console.WriteLine("MyHost: NotifyBeginApplication");
|
||||
return;
|
||||
}
|
||||
|
||||
public override void NotifyEndApplication()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
public override void SetShouldExit(int exitCode)
|
||||
{
|
||||
Console.WriteLine("SetShouldExit: " + exitCode);
|
||||
}
|
||||
}
|
||||
|
||||
class Program
|
||||
{
|
||||
|
||||
private static void ReportException(Exception e)
|
||||
{
|
||||
if (e != null)
|
||||
{
|
||||
object error;
|
||||
IContainsErrorRecord icer = e as IContainsErrorRecord;
|
||||
if (icer != null)
|
||||
{
|
||||
error = icer.ErrorRecord;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = (object)new ErrorRecord(e, "Host.ReportException", ErrorCategory.NotSpecified, null);
|
||||
}
|
||||
|
||||
// this should be output through PowerShell, but for simplicity just output it here
|
||||
Console.WriteLine(error.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
static void test2(string[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
MyHost myHost = new MyHost(new Program());
|
||||
|
||||
InitialSessionState iss = InitialSessionState.CreateDefault2();
|
||||
|
||||
using (Runspace rs = RunspaceFactory.CreateRunspace(myHost,iss))
|
||||
{
|
||||
rs.Open();
|
||||
foreach (var arg in args)
|
||||
{
|
||||
using (PowerShell ps = PowerShell.Create())
|
||||
{
|
||||
ps.Runspace = rs;
|
||||
|
||||
Console.WriteLine("script: " + arg);
|
||||
ps.AddScript(arg);
|
||||
ps.AddCommand("out-default");
|
||||
ps.Commands.Commands[0].MergeMyResults(PipelineResultTypes.Error,PipelineResultTypes.Output);
|
||||
ps.Invoke();
|
||||
ps.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (RuntimeException ex)
|
||||
{
|
||||
ReportException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
test2(args);
|
||||
}
|
||||
}
|
||||
}
|
12
src/xunit-tests/xunit-tests.mk
Normal file
12
src/xunit-tests/xunit-tests.mk
Normal file
|
@ -0,0 +1,12 @@
|
|||
# xUnit tests for PowerShell
|
||||
# - results in xunit-tests.xml
|
||||
# - see https://xunit.github.io/
|
||||
TEST_FOLDER=$(MONAD)/src/xunit-tests
|
||||
TEST_SRCS=$(TEST_FOLDER)/test_*.cs
|
||||
TEST_TARGETS=$(addprefix $(PSLIB)/, System.Management.Automation.dll Microsoft.PowerShell.Commands.Management.dll)
|
||||
|
||||
$(PSLIB)/PowerShell.Linux.Test.dll: $(TEST_SRCS) $(TEST_TARGETS)
|
||||
$(CSC) $(CSCOPTS_LIB) -out:$@ $(addprefix -r:$(MONAD_EXT)/xunit/, xunit.core.dll xunit.assert.dll) $(addprefix -r:, $(TEST_TARGETS)) $(COREREF) $(TEST_SRCS)
|
||||
|
||||
test: $(PSLIB)/PowerShell.Linux.Test.dll
|
||||
$(POWERSHELL_HOST) $(PSLIB)/xunit.console.netcore.exe $< -xml $(MONAD)/xunit-tests.xml
|
Loading…
Reference in a new issue