2016-07-20 02:21:32 +02:00
|
|
|
Describe 'Attributes Test' -Tags "CI" {
|
2017-01-16 22:31:14 +01:00
|
|
|
|
|
|
|
BeforeAll {
|
2016-07-19 22:52:03 +02:00
|
|
|
$dummyAttributesSource = @'
|
|
|
|
using System.Management.Automation;
|
|
|
|
namespace Dummy
|
|
|
|
{
|
|
|
|
public class DoubleStringTransformationAttribute : ArgumentTransformationAttribute
|
|
|
|
{
|
|
|
|
public override object Transform(EngineIntrinsics engineIntrinsics, object inputData)
|
|
|
|
{
|
|
|
|
string arg = inputData as string;
|
|
|
|
if (arg != null)
|
|
|
|
{
|
|
|
|
return arg + arg;
|
|
|
|
}
|
|
|
|
return inputData;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public class AppendStringTransformationAttribute : ArgumentTransformationAttribute
|
|
|
|
{
|
|
|
|
public override object Transform(EngineIntrinsics engineIntrinsics, object inputData)
|
|
|
|
{
|
|
|
|
string arg = inputData as string;
|
|
|
|
if (arg != null)
|
|
|
|
{
|
|
|
|
return arg + "___";
|
|
|
|
}
|
|
|
|
return inputData;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public class DoubleInt : ArgumentTransformationAttribute
|
|
|
|
{
|
|
|
|
public override object Transform(EngineIntrinsics engineIntrinsics, object inputData)
|
|
|
|
{
|
|
|
|
int? arg = inputData as int?;
|
|
|
|
if (arg != null)
|
|
|
|
{
|
|
|
|
return arg + arg;
|
|
|
|
}
|
|
|
|
return inputData;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-01-16 22:31:14 +01:00
|
|
|
'@
|
Move powershell to .NET Core 2.0 (#3556)
This change moves powershell to .NET Core 2.0. Major changes are:
1. PowerShell assemblies are now targeting `netcoreapp2.0`. We are using `microsoft.netcore.app-2.0.0-preview1-001913-00`, which is from dotnet-core build 4/4/17. We cannot target `netstandard2.0` because the packages `System.Reflection.Emit` and `System.Reflection.Emit.Lightweight`, which are needed for powershell class, cannot be referenced when targeting `netstandard2.0`.
2. Refactor code to remove most CLR stub types and extension types.
3. Update build scripts to enable CI builds. The `-cache` section is specified to depend on `appveyor.yml`, so the cache will be invalidated if `appveyor.yml` is changed.
4. Ship `netcoreapp` reference assemblies with powershell to fix the issues in `Add-Type` (#2764). By default `Add-Type` will reference all those reference assemblies when compiling C# code. If `-ReferenceAssembly` is specified, then we search reference assemblies first, then the framework runtime assemblies, and lastly the loaded assemblies (possibly a third-party one that was already loaded).
5. `dotnet publish` generates executable on Unix platforms, but doesn't set "x" permission and thus it cannot execute. Currently, the "x" permission is set in the build script, `dotnet/cli` issue [#6286](https://github.com/dotnet/cli/issues/6286) is tracking this.
6. Replace the use of some APIs with the ones that take `SecureString`.
7. osx.10.12 is required to update to `netcoreapp2.0` because `dotnet-cli` 2.0.0-preview only works on osx.10.12.
8. Add dependency to `System.ValueTuple` to work around a ambiguous type identity issue in coreclr. The issue is tracked by `dotnet/corefx` [#17797](https://github.com/dotnet/corefx/issues/17797). When moving to newer version of `netcoreapp2.0`, we need to verify if this dependency is still needed.
2017-04-17 20:52:38 +02:00
|
|
|
Add-Type -TypeDefinition $dummyAttributesSource
|
2016-07-19 22:52:03 +02:00
|
|
|
}
|
|
|
|
|
2017-01-16 22:31:14 +01:00
|
|
|
|
|
|
|
|
2016-07-19 22:52:03 +02:00
|
|
|
Context 'Property.Instance.ValidateSet.String' {
|
|
|
|
class C1 { [ValidateSet("Present", "Absent")][string]$Ensure }
|
|
|
|
# This call should not throw exception
|
|
|
|
[C1]::new().Ensure = "Present"
|
|
|
|
|
|
|
|
It 'Error when ValidateSet should be ExceptionWhenSetting' {
|
|
|
|
try
|
|
|
|
{
|
|
|
|
[C1]::new().Ensure = "foo"
|
|
|
|
throw "Exception expected"
|
|
|
|
}
|
|
|
|
catch
|
2017-01-16 22:31:14 +01:00
|
|
|
{
|
2016-07-19 22:52:03 +02:00
|
|
|
$_.FullyQualifiedErrorId | Should be 'ExceptionWhenSetting'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Context 'Property.Static.ValidateSet.String' {
|
|
|
|
class C1 { static [ValidateSet("Present", "Absent")][string]$Ensure }
|
|
|
|
# This call should not throw exception
|
|
|
|
[C1]::Ensure = "Present"
|
|
|
|
It 'Error when ValidateSet should be ExceptionWhenSetting'{
|
2017-01-16 22:31:14 +01:00
|
|
|
try {
|
2016-07-19 22:52:03 +02:00
|
|
|
[C1]::Ensure = "foo"
|
|
|
|
throw "Exception expected"
|
|
|
|
}
|
2017-01-16 22:31:14 +01:00
|
|
|
catch {
|
2016-07-19 22:52:03 +02:00
|
|
|
$_.FullyQualifiedErrorId | Should be 'ExceptionWhenSetting'
|
2017-01-16 22:31:14 +01:00
|
|
|
}
|
|
|
|
}
|
2016-07-19 22:52:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Context 'Property.Instance.ValidateRange.Int' {
|
|
|
|
class C1 { [ValidateRange(1, 10)][int]$f }
|
|
|
|
# This call should not throw exception
|
|
|
|
[C1]::new().f = 10
|
|
|
|
[C1]::new().f = 1
|
|
|
|
It 'Error when ValidateSet should be ExceptionWhenSetting'{
|
|
|
|
try {
|
|
|
|
[C1]::new().f = 20
|
|
|
|
throw "Exception expected"
|
|
|
|
}
|
2017-01-16 22:31:14 +01:00
|
|
|
catch {
|
2016-07-19 22:52:03 +02:00
|
|
|
$_.FullyQualifiedErrorId | Should be 'ExceptionWhenSetting'
|
2017-01-16 22:31:14 +01:00
|
|
|
}
|
|
|
|
}
|
2016-07-19 22:52:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Context 'Property.Static.ValidateRange.Int' {
|
|
|
|
class C1 { static [ValidateRange(1, 10)][int]$f }
|
|
|
|
# This call should not throw exception
|
|
|
|
[C1]::f = 5
|
|
|
|
It 'Error when ValidateSet should be ExceptionWhenSetting'{
|
|
|
|
try {
|
|
|
|
[C1]::f = 20
|
|
|
|
throw "Exception expected"
|
|
|
|
}
|
2017-01-16 22:31:14 +01:00
|
|
|
catch {
|
2016-07-19 22:52:03 +02:00
|
|
|
$_.FullyQualifiedErrorId | Should be 'ExceptionWhenSetting'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Context 'Property.Static.ValidateSet.ImplicitObject' {
|
|
|
|
class C1 { static [ValidateSet("abc", 5)]$o }
|
|
|
|
# This call should not throw exception
|
|
|
|
[C1]::o = "abc"
|
|
|
|
[C1]::o = 5
|
|
|
|
It 'Error when ValidateSet should be ExceptionWhenSetting'{
|
|
|
|
try {
|
|
|
|
[C1]::o = 1
|
|
|
|
throw "Exception expected"
|
|
|
|
}
|
2017-01-16 22:31:14 +01:00
|
|
|
catch {
|
2016-07-19 22:52:03 +02:00
|
|
|
$_.FullyQualifiedErrorId | Should be 'ExceptionWhenSetting'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#
|
|
|
|
# We use [scriptblock]::Create() here to allow SuiteSetup add Dummy.Transformation type to
|
|
|
|
# the scope. Otherwise, we will need to have all classes for attributes in parse time.
|
|
|
|
#
|
|
|
|
# Invoke() returns an array, we need first element of it.
|
|
|
|
#
|
2017-01-16 22:31:14 +01:00
|
|
|
|
2016-07-19 22:52:03 +02:00
|
|
|
Context 'Property.Instance.Transformation.ImplicitObject' {
|
|
|
|
$c = [scriptblock]::Create('class C1 { [Dummy.DoubleStringTransformation()]$arg }; [C1]::new()').Invoke()[0]
|
2017-01-16 22:31:14 +01:00
|
|
|
|
2016-07-19 22:52:03 +02:00
|
|
|
It 'Implicitly Transform to 100' {
|
|
|
|
$c.arg = 100
|
|
|
|
$c.arg | should be 100
|
|
|
|
}
|
|
|
|
It 'Implicitly Transform to foo' {
|
|
|
|
$c.arg = "foo"
|
|
|
|
$c.arg | should be "foofoo"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Context 'Property.Instance.Transformation.String' {
|
|
|
|
$c = [scriptblock]::Create('class C1 { [Dummy.DoubleStringTransformation()][string]$arg }; [C1]::new()').Invoke()[0]
|
|
|
|
It 'set to foo' {
|
|
|
|
$c.arg = "foo"
|
|
|
|
$c.arg | should be "foofoo"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Context Property.Instance.Transformation.Int {
|
2017-01-16 22:31:14 +01:00
|
|
|
$c = [scriptblock]::Create('class C1 { [Dummy.DoubleInt()][int]$arg }; [C1]::new()').Invoke()[0]
|
2016-07-19 22:52:03 +02:00
|
|
|
It 'arg should be 200' {
|
|
|
|
$c.arg = 100
|
|
|
|
$c.arg | should be 200
|
|
|
|
}
|
2017-01-16 22:31:14 +01:00
|
|
|
It 'Set to string should fail with ExceptionWhenSetting' {
|
2016-07-19 22:52:03 +02:00
|
|
|
try {
|
|
|
|
$c.arg = "abc"
|
|
|
|
throw "Exception expected"
|
|
|
|
}
|
2017-01-16 22:31:14 +01:00
|
|
|
catch {
|
2016-07-19 22:52:03 +02:00
|
|
|
$_.FullyQualifiedErrorId | Should be 'ExceptionWhenSetting'
|
|
|
|
}
|
2017-01-16 22:31:14 +01:00
|
|
|
}
|
2016-07-19 22:52:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Context Property.Instance.Transformation.Nullable {
|
|
|
|
$c = [scriptblock]::Create('class C1 { [Nullable[int]][Dummy.DoubleStringTransformation()]$arg }; [C1]::new()').Invoke()[0]
|
|
|
|
It 'arg should be 100' {
|
|
|
|
$c.arg = 100
|
|
|
|
$c.arg | should be 100
|
2017-01-16 22:31:14 +01:00
|
|
|
}
|
2016-07-19 22:52:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Context Property.Instance.Transformation.Order {
|
|
|
|
$c = [scriptblock]::Create('class C1 { [Dummy.DoubleStringTransformation()][Dummy.AppendStringTransformation()]$arg }; [C1]::new()').Invoke()[0]
|
|
|
|
It 'arg should be 100' {
|
|
|
|
$c.arg = 100
|
|
|
|
$c.arg | should be 100
|
|
|
|
}
|
2017-01-16 22:31:14 +01:00
|
|
|
|
2016-07-19 22:52:03 +02:00
|
|
|
It 'arg should be foo___foo___g' {
|
|
|
|
$c.arg = "foo"
|
|
|
|
$c.arg | should be "foo___foo___"
|
|
|
|
}
|
2017-01-16 22:31:14 +01:00
|
|
|
}
|
2016-07-19 22:52:03 +02:00
|
|
|
}
|
|
|
|
|
2016-07-20 02:21:32 +02:00
|
|
|
Describe 'Type resolution with attributes' -Tag "CI" {
|
2017-01-16 22:31:14 +01:00
|
|
|
# There is kind of a collision between names
|
2016-07-19 22:52:03 +02:00
|
|
|
# System.Diagnostics.Tracing.EventSource
|
|
|
|
# System.Diagnostics.Tracing.EventSourceAttribute
|
|
|
|
# We need to make sure that we resolve type name to the right class at each usage
|
|
|
|
Context 'Name collision' {
|
2017-01-16 22:31:14 +01:00
|
|
|
|
2016-07-19 22:52:03 +02:00
|
|
|
It 'Resolve System.Diagnostics.Tracing.EventSource to Attribute and to Type in the different contexts' {
|
|
|
|
[System.Diagnostics.Tracing.EventSource(Name = "MyPSEventSource")]
|
2017-01-16 22:31:14 +01:00
|
|
|
class MyEventSource : System.Diagnostics.Tracing.EventSource
|
|
|
|
{
|
|
|
|
[void] OnEvent([string]$Message) {}
|
2016-07-19 22:52:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
[MyEventSource]::new() | Should Not Be $null
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
2016-07-20 02:21:32 +02:00
|
|
|
}
|
2017-07-14 06:28:32 +02:00
|
|
|
|
|
|
|
Describe 'ValidateSet support a dynamically generated set' -Tag "CI" {
|
|
|
|
|
|
|
|
Context 'C# tests' {
|
|
|
|
|
|
|
|
BeforeAll {
|
|
|
|
$a=@'
|
|
|
|
using System;
|
|
|
|
using System.Management.Automation;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
|
|
namespace Test.Language {
|
|
|
|
|
|
|
|
[Cmdlet(VerbsCommon.Get, "TestValidateSet0")]
|
|
|
|
public class TestValidateSetCommand0 : PSCmdlet
|
|
|
|
{
|
|
|
|
[Parameter]
|
|
|
|
[ValidateSet(typeof(PSCmdlet))]
|
|
|
|
public string Param1;
|
|
|
|
|
|
|
|
protected override void EndProcessing()
|
|
|
|
{
|
|
|
|
WriteObject(Param1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[Cmdlet(VerbsCommon.Get, "TestValidateSet4")]
|
|
|
|
public class TestValidateSetCommand4 : PSCmdlet
|
|
|
|
{
|
|
|
|
[Parameter]
|
|
|
|
[ValidateSet(typeof(GenValuesForParam))]
|
|
|
|
public string Param1;
|
|
|
|
|
|
|
|
protected override void EndProcessing()
|
|
|
|
{
|
|
|
|
WriteObject(Param1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[Cmdlet(VerbsCommon.Get, "TestValidateSet5")]
|
|
|
|
public class TestValidateSetCommand5 : PSCmdlet
|
|
|
|
{
|
|
|
|
[Parameter]
|
|
|
|
[ValidateSet(typeof(GenValuesForParamNull))]
|
|
|
|
public string Param1;
|
|
|
|
|
|
|
|
protected override void EndProcessing()
|
|
|
|
{
|
|
|
|
WriteObject(Param1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Implement of test IValidateSetValuesGenerator
|
|
|
|
public class GenValuesForParamNull : IValidateSetValuesGenerator
|
|
|
|
{
|
|
|
|
public string[] GetValidValues()
|
|
|
|
{
|
|
|
|
var testValues = new string[] {"Test1","TestString1","Test2"};
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public class GenValuesForParam : IValidateSetValuesGenerator
|
|
|
|
{
|
|
|
|
public string[] GetValidValues()
|
|
|
|
{
|
|
|
|
var testValues = new string[] {"Test1","TestString1","Test2"};
|
|
|
|
return testValues;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
'@
|
|
|
|
|
|
|
|
$testAssemply = "$TestDrive\tst-$(New-Guid).dll"
|
|
|
|
Add-Type -TypeDefinition $a -OutputAssembly $testAssemply
|
|
|
|
Import-Module $testAssemply
|
|
|
|
}
|
|
|
|
|
|
|
|
It 'Throw if IValidateSetValuesGenerator is not implemented' {
|
|
|
|
{ Get-TestValidateSet0 -Param1 "TestString" -ErrorAction Stop } | ShouldBeErrorId "Argument"
|
|
|
|
}
|
|
|
|
|
|
|
|
It 'Dynamically generated set works in C# with default (immediate) cache expire' {
|
|
|
|
Get-TestValidateSet4 -Param1 "TestString1" -ErrorAction SilentlyContinue | Should BeExactly "TestString1"
|
|
|
|
}
|
|
|
|
|
|
|
|
It 'Empty dynamically generated set throws in C#' {
|
|
|
|
$exc = {
|
|
|
|
Get-TestValidateSet5 -Param1 "TestString1" -ErrorAction Stop
|
|
|
|
} | ShouldBeErrorId "ParameterArgumentValidationError,Test.Language.TestValidateSetCommand5"
|
|
|
|
$exc.Exception.InnerException.ErrorRecord.FullyQualifiedErrorId | Should BeExactly "ValidateSetGeneratedValidValuesListIsNull"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Context 'Powershell tests' {
|
|
|
|
|
|
|
|
BeforeAll {
|
|
|
|
class GenValuesForParam : System.Management.Automation.IValidateSetValuesGenerator {
|
|
|
|
[String[]] GetValidValues() {
|
|
|
|
|
|
|
|
return [string[]]("Test1","TestString1","Test2")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class GenValuesForParamNull : System.Management.Automation.IValidateSetValuesGenerator {
|
|
|
|
[String[]] GetValidValues() {
|
|
|
|
|
|
|
|
return [string[]]$null
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# Return '$testValues2' and after 2 seconds after first use return another array '$testValues1'.
|
|
|
|
class GenValuesForParamCache1 : System.Management.Automation.IValidateSetValuesGenerator {
|
|
|
|
[String[]] GetValidValues() {
|
|
|
|
|
|
|
|
$testValues1 = "Test11","TestString11","Test22"
|
|
|
|
$testValues2 = "Test11","TestString22","Test22"
|
|
|
|
|
|
|
|
$currentTime = [DateTime]::Now
|
|
|
|
if ([DateTime]::Compare([GenValuesForParamCache1]::cacheTime, $currentTime) -le 0)
|
|
|
|
{
|
|
|
|
$testValues = $testValues1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$testValues = $testValues2;
|
|
|
|
}
|
|
|
|
return [string[]]$testValues
|
|
|
|
}
|
|
|
|
|
|
|
|
static [DateTime] $cacheTime = [DateTime]::Now.AddSeconds(2);
|
|
|
|
}
|
|
|
|
|
|
|
|
function Get-TestValidateSetPS4
|
|
|
|
{
|
|
|
|
[CmdletBinding()]
|
|
|
|
Param
|
|
|
|
(
|
|
|
|
[ValidateSet([GenValuesForParam])]
|
|
|
|
$Param1
|
|
|
|
)
|
|
|
|
|
|
|
|
$Param1
|
|
|
|
}
|
|
|
|
|
|
|
|
function Get-TestValidateSetPS5
|
|
|
|
{
|
|
|
|
[CmdletBinding()]
|
|
|
|
Param
|
|
|
|
(
|
|
|
|
[ValidateSet([GenValuesForParamNull])]
|
|
|
|
$Param1
|
|
|
|
)
|
|
|
|
|
|
|
|
$Param1
|
|
|
|
}
|
|
|
|
|
|
|
|
function Get-TestValidateSetPS6
|
|
|
|
{
|
|
|
|
[CmdletBinding()]
|
|
|
|
Param
|
|
|
|
(
|
|
|
|
[ValidateSet([UnImplementedGeneratorOfValues])]
|
|
|
|
$Param1
|
|
|
|
)
|
|
|
|
|
|
|
|
$Param1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
It 'Dynamically generated set works in PowerShell script with default (immediate) cache expire' {
|
|
|
|
Get-TestValidateSetPS4 -Param1 "TestString1" -ErrorAction SilentlyContinue | Should BeExactly "TestString1"
|
|
|
|
}
|
|
|
|
|
|
|
|
It 'Empty dynamically generated set throws in PowerShell script' {
|
|
|
|
$exc = {
|
|
|
|
Get-TestValidateSetPS5 -Param1 "TestString1" -ErrorAction Stop
|
|
|
|
} | ShouldBeErrorId "ParameterArgumentValidationError,Get-TestValidateSetPS5"
|
|
|
|
$exc.Exception.InnerException.ErrorRecord.FullyQualifiedErrorId | Should BeExactly "ValidateSetGeneratedValidValuesListIsNull"
|
|
|
|
}
|
|
|
|
|
|
|
|
It 'Unimplemented valid values generator type throws in PowerShell script' {
|
|
|
|
{
|
|
|
|
Get-TestValidateSetPS6 -Param1 "AnyTestString" -ErrorAction Stop
|
|
|
|
} | ShouldBeErrorId "TypeNotFound"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Context 'CachedValidValuesGeneratorBase class tests' {
|
|
|
|
|
|
|
|
BeforeAll {
|
|
|
|
class GenValuesForParam : System.Management.Automation.CachedValidValuesGeneratorBase {
|
|
|
|
GenValuesForParam() : base(300) {
|
|
|
|
}
|
|
|
|
|
|
|
|
[String[]] GenerateValidValues() {
|
|
|
|
|
|
|
|
return [string[]]("Test1","TestString1","Test2")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class GenValuesWithExpiration : System.Management.Automation.CachedValidValuesGeneratorBase {
|
|
|
|
GenValuesWithExpiration() : base(2) {
|
|
|
|
}
|
|
|
|
|
|
|
|
Static [bool] $temp = $true;
|
|
|
|
|
|
|
|
[String[]] GenerateValidValues() {
|
|
|
|
|
|
|
|
if ([GenValuesWithExpiration]::temp) {
|
|
|
|
[GenValuesWithExpiration]::temp = $false
|
|
|
|
return [string[]]("Test1","TestString1","Test2")
|
|
|
|
} else {
|
|
|
|
[GenValuesWithExpiration]::temp = $true
|
|
|
|
return [string[]]("Test1","TestString2","Test2")
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function Get-TestValidateSetPS4
|
|
|
|
{
|
|
|
|
[CmdletBinding()]
|
|
|
|
Param
|
|
|
|
(
|
|
|
|
[ValidateSet([GenValuesForParam])]
|
|
|
|
$Param1
|
|
|
|
)
|
|
|
|
|
|
|
|
$Param1
|
|
|
|
}
|
|
|
|
|
|
|
|
function Get-TestValidateSetPS5
|
|
|
|
{
|
|
|
|
[CmdletBinding()]
|
|
|
|
Param
|
|
|
|
(
|
|
|
|
[ValidateSet([GenValuesWithExpiration])]
|
|
|
|
$Param1
|
|
|
|
)
|
|
|
|
|
|
|
|
$Param1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
It 'Can implement CachedValidValuesGeneratorBase in PowerShell' {
|
|
|
|
Get-TestValidateSetPS4 -Param1 "TestString1" -ErrorAction SilentlyContinue | Should BeExactly "TestString1"
|
|
|
|
}
|
|
|
|
|
|
|
|
It 'Can implement CachedValidValuesGeneratorBase with cache expiration in PowerShell' {
|
|
|
|
Get-TestValidateSetPS5 -Param1 "TestString1" -ErrorAction SilentlyContinue | Should BeExactly "TestString1"
|
|
|
|
Get-TestValidateSetPS5 -Param1 "TestString1" -ErrorAction SilentlyContinue | Should BeExactly "TestString1"
|
|
|
|
Start-Sleep 3
|
|
|
|
Get-TestValidateSetPS5 -Param1 "TestString2" -ErrorAction SilentlyContinue | Should BeExactly "TestString2"
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|