2018-02-13 18:23:53 +01:00
|
|
|
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
# Licensed under the MIT License.
|
2017-07-15 03:05:48 +02:00
|
|
|
Describe "Additional static method tests" -Tags "CI" {
|
|
|
|
|
|
|
|
Context "Basic static member methods" {
|
|
|
|
BeforeAll {
|
|
|
|
function Get-Name { "YES" }
|
|
|
|
}
|
|
|
|
|
|
|
|
It "test basic static constructor" {
|
|
|
|
class Foo {
|
|
|
|
static [string] $Name
|
|
|
|
static Foo() { [Foo]::Name = Get-Name }
|
|
|
|
}
|
|
|
|
|
2018-03-21 18:47:08 +01:00
|
|
|
[Foo]::Name | Should -Be "Yes"
|
2017-07-15 03:05:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
It "test basic static method" {
|
|
|
|
class Foo {
|
|
|
|
static [string] GetName() { return (Get-Name) }
|
|
|
|
}
|
|
|
|
|
2018-03-21 18:47:08 +01:00
|
|
|
[Foo]::GetName() | Should -Be "Yes"
|
2017-07-15 03:05:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Context "Class defined in different Runspace" {
|
|
|
|
BeforeAll {
|
|
|
|
@'
|
|
|
|
class Foo
|
|
|
|
{
|
|
|
|
static [string] $Name
|
|
|
|
static Foo() { [Foo]::Name = Get-Name }
|
|
|
|
|
|
|
|
static [string] GetName()
|
|
|
|
{
|
|
|
|
return (Get-AnotherName)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
'@ | Set-Content -Path $TestDrive\class.ps1 -Force
|
|
|
|
|
|
|
|
## Define the functions that [Foo] depends on in the default Runspace.
|
|
|
|
function Get-Name { "Default Runspace - Name" }
|
|
|
|
function Get-AnotherName { "Default Runspace - AnotherName" }
|
|
|
|
|
|
|
|
## Create another Runspace PS1
|
|
|
|
$ps1 = [powershell]::Create()
|
|
|
|
## Create another Runspace PS2
|
|
|
|
$ps2 = [powershell]::Create()
|
|
|
|
|
|
|
|
function RunScriptInPS {
|
|
|
|
param(
|
|
|
|
[powershell] $PowerShell,
|
|
|
|
[string] $Script,
|
|
|
|
[switch] $IgnoreResult
|
|
|
|
)
|
|
|
|
$result = $PowerShell.AddScript($Script).Invoke()
|
|
|
|
$PowerShell.Commands.Clear()
|
|
|
|
|
|
|
|
if (-not $IgnoreResult) {
|
|
|
|
return $result
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
## Define the functions that [Foo] depends on in PS1 Runspace.
|
|
|
|
RunScriptInPS -PowerShell $ps1 -Script "function Get-Name { 'PS1 Runspace - Name' }" -IgnoreResult
|
|
|
|
RunScriptInPS -PowerShell $ps1 -Script "function Get-AnotherName { 'PS1 Runspace - AnotherName' }" -IgnoreResult
|
|
|
|
|
|
|
|
# Dot source class.ps1 in the current Runspace
|
|
|
|
. $TestDrive\class.ps1
|
|
|
|
# And then dot source class.ps1 in the PS1 Runspace
|
|
|
|
RunScriptInPS -PowerShell $ps1 -Script ". $TestDrive\class.ps1" -IgnoreResult
|
|
|
|
}
|
|
|
|
|
|
|
|
AfterAll {
|
|
|
|
# Dispose both Runspaces
|
|
|
|
$ps1.Dispose()
|
|
|
|
$ps2.Dispose()
|
|
|
|
}
|
|
|
|
|
|
|
|
It "Static constructor should run in the triggering Runspace if the class has been defined in that Runspace" {
|
|
|
|
|
|
|
|
## The static constructor is triggered by accessing '[Foo]::Name' which happens in the current Runspace.
|
|
|
|
## The class 'Foo' has been defined in the current Runspace, so it uses the current Runspace to run the
|
|
|
|
## static constructor.
|
2018-03-21 18:47:08 +01:00
|
|
|
[Foo]::Name | Should -BeExactly "Default Runspace - Name"
|
2017-07-15 03:05:48 +02:00
|
|
|
|
|
|
|
## Static constructor runs only once, so accessing the Name property in the PS1 Runspace will just return
|
|
|
|
## the existing value.
|
2018-03-21 18:47:08 +01:00
|
|
|
RunScriptInPS -PowerShell $ps1 -Script "[Foo]::Name" | Should -BeExactly "Default Runspace - Name"
|
2017-07-15 03:05:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
It "Static method use the Runspace where the call happens if the class has been defined in that Runspace" {
|
|
|
|
|
|
|
|
## We call the static method in the current Runspace. The class 'Foo' has been defined
|
|
|
|
## in the current Runspace, so it will use it to run the method.
|
2018-03-21 18:47:08 +01:00
|
|
|
[Foo]::GetName() | Should -BeExactly "Default Runspace - AnotherName"
|
2017-07-15 03:05:48 +02:00
|
|
|
|
|
|
|
## We call the static method in PS1 Runspace. The class 'Foo' has been defined in the
|
|
|
|
## PS1 Runspace, so it will use it to run the method.
|
2018-03-21 18:47:08 +01:00
|
|
|
RunScriptInPS -PowerShell $ps1 -Script "[Foo]::GetName()" | Should -BeExactly 'PS1 Runspace - AnotherName'
|
2017-07-15 03:05:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
It "Static method use the default SessionState if it's called in a Runspace where the class is not defined" {
|
|
|
|
|
|
|
|
## Define the functions that [Foo] depends on in PS2 Runspace.
|
|
|
|
RunScriptInPS -PowerShell $ps2 -Script "function Get-Name { 'PS2 Runspace - Name' }" -IgnoreResult
|
|
|
|
RunScriptInPS -PowerShell $ps2 -Script "function Get-AnotherName { 'PS2 Runspace - AnotherName' }" -IgnoreResult
|
|
|
|
|
|
|
|
## Define the function to call the static method 'GetName' on the passed-in type
|
|
|
|
RunScriptInPS -PowerShell $ps2 -Script 'function Call-GetName([type] $type) { $type::GetName() }' -IgnoreResult
|
|
|
|
|
|
|
|
## We call the static method in PS2 Runspace. The class is not defined in this Runspace,
|
|
|
|
## so the default SessionState will be used to run the method. The default SessionState
|
|
|
|
## is always the one where the class was defined most recently. In this case, the class
|
|
|
|
## was lastly defined in PS1 Runspace, os the method will be invoked in PS1 Runspace.
|
|
|
|
$result = $ps2.AddCommand("Call-GetName").AddParameter("type", [Foo]).Invoke()
|
2018-03-21 18:47:08 +01:00
|
|
|
$result | Should -BeExactly 'PS1 Runspace - AnotherName'
|
2017-07-15 03:05:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|