mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Move cross platform DSC code to a subsystem (#15127)
This commit is contained in:
@@ -13,6 +13,7 @@ using System.Runtime.CompilerServices;
|
||||
[assembly: InternalsVisibleTo(@"Microsoft.PowerShell.Security" + @",PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
|
||||
[assembly: InternalsVisibleTo(@"System.Management.Automation.Remoting" + @",PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
|
||||
[assembly: InternalsVisibleTo(@"Microsoft.PowerShell.ConsoleHost" + @",PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
|
||||
[assembly: InternalsVisibleTo(@"Microsoft.PowerShell.DscSubsystem" + @",PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
|
||||
|
||||
namespace System.Management.Automation
|
||||
{
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Management.Automation;
|
||||
using System.Security;
|
||||
|
||||
namespace Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform
|
||||
{
|
||||
/// <summary>
|
||||
/// Class that does high level Cim schema parsing.
|
||||
/// </summary>
|
||||
internal class CimDSCParser
|
||||
{
|
||||
private readonly JsonDeserializer _jsonDeserializer;
|
||||
|
||||
internal CimDSCParser()
|
||||
{
|
||||
_jsonDeserializer = JsonDeserializer.Create();
|
||||
}
|
||||
|
||||
internal IEnumerable<PSObject> ParseSchemaJson(string filePath, bool useNewRunspace = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
string json = File.ReadAllText(filePath);
|
||||
string fileNameDefiningClass = Path.GetFileNameWithoutExtension(filePath);
|
||||
int dotIndex = fileNameDefiningClass.IndexOf(".schema", StringComparison.InvariantCultureIgnoreCase);
|
||||
if (dotIndex != -1)
|
||||
{
|
||||
fileNameDefiningClass = fileNameDefiningClass.Substring(0, dotIndex);
|
||||
}
|
||||
|
||||
IEnumerable<PSObject> result = _jsonDeserializer.DeserializeClasses(json, useNewRunspace);
|
||||
foreach (dynamic classObject in result)
|
||||
{
|
||||
string superClassName = classObject.SuperClassName;
|
||||
string className = classObject.ClassName;
|
||||
if (string.Equals(superClassName, "OMI_BaseResource", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// Get the name of the file without schema.mof/json extension
|
||||
if (!className.Equals(fileNameDefiningClass, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
PSInvalidOperationException e = PSTraceSource.NewInvalidOperationException(
|
||||
ParserStrings.ClassNameNotSameAsDefiningFile, className, fileNameDefiningClass);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
PSInvalidOperationException e = PSTraceSource.NewInvalidOperationException(
|
||||
exception, ParserStrings.CimDeserializationError, filePath);
|
||||
|
||||
e.SetErrorId("CimDeserializationError");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Management.Automation;
|
||||
using System.Management.Automation.Runspaces;
|
||||
|
||||
namespace Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform
|
||||
{
|
||||
internal class JsonDeserializer
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a default deserializer.
|
||||
/// </summary>
|
||||
/// <returns>Default deserializer.</returns>
|
||||
public static JsonDeserializer Create()
|
||||
{
|
||||
return new JsonDeserializer();
|
||||
}
|
||||
|
||||
#endregion Constructors
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// Returns schema of Cim classes from specified json file.
|
||||
/// </summary>
|
||||
/// <param name="json">Json text to deserialize.</param>
|
||||
/// <param name="useNewRunspace">If a new runspace should be used.</param>
|
||||
/// <returns>Deserialized PSObjects.</returns>
|
||||
public IEnumerable<PSObject> DeserializeClasses(string json, bool useNewRunspace = false)
|
||||
{
|
||||
if (string.IsNullOrEmpty(json))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(json));
|
||||
}
|
||||
|
||||
System.Management.Automation.PowerShell powerShell = null;
|
||||
|
||||
if (useNewRunspace)
|
||||
{
|
||||
// currently using RunspaceMode.NewRunspace will reset PSModulePath env var for the entire process
|
||||
// this is something we want to avoid in DSC GuestConfigAgent scenario, so we use following workaround
|
||||
var s_iss = InitialSessionState.CreateDefault();
|
||||
s_iss.EnvironmentVariables.Add(
|
||||
new SessionStateVariableEntry(
|
||||
"PSModulePath",
|
||||
Environment.GetEnvironmentVariable("PSModulePath"),
|
||||
description: null));
|
||||
powerShell = System.Management.Automation.PowerShell.Create(s_iss);
|
||||
}
|
||||
else
|
||||
{
|
||||
powerShell = System.Management.Automation.PowerShell.Create(RunspaceMode.CurrentRunspace);
|
||||
}
|
||||
|
||||
using (powerShell)
|
||||
{
|
||||
return powerShell.AddCommand("Microsoft.PowerShell.Utility\\ConvertFrom-Json")
|
||||
.AddParameter("InputObject", json)
|
||||
.AddParameter("Depth", 100) // maximum supported by cmdlet
|
||||
.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Methods
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,6 +9,8 @@ using System.Management.Automation.Language;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Management.Automation.Subsystem;
|
||||
using System.Management.Automation.Subsystem.DSC;
|
||||
|
||||
namespace System.Management.Automation
|
||||
{
|
||||
@@ -1721,9 +1723,16 @@ namespace System.Management.Automation
|
||||
|
||||
foreach (var keyword in matchedResults)
|
||||
{
|
||||
string usageString = Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform.DscClassCache.NewApiIsUsed
|
||||
? Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform.DscClassCache.GetDSCResourceUsageString(keyword)
|
||||
: Microsoft.PowerShell.DesiredStateConfiguration.Internal.DscClassCache.GetDSCResourceUsageString(keyword);
|
||||
string usageString = string.Empty;
|
||||
ICrossPlatformDsc dscSubsystem = SubsystemManager.GetSubsystem<ICrossPlatformDsc>();
|
||||
if (dscSubsystem != null)
|
||||
{
|
||||
usageString = dscSubsystem.GetDSCResourceUsageString(keyword);
|
||||
}
|
||||
else
|
||||
{
|
||||
usageString = Microsoft.PowerShell.DesiredStateConfiguration.Internal.DscClassCache.GetDSCResourceUsageString(keyword);
|
||||
}
|
||||
|
||||
if (results == null)
|
||||
{
|
||||
|
||||
@@ -125,9 +125,6 @@ namespace System.Management.Automation
|
||||
new ExperimentalFeature(
|
||||
name: "PSNotApplyErrorActionToStderr",
|
||||
description: "Don't have $ErrorActionPreference affect stderr output"),
|
||||
new ExperimentalFeature(
|
||||
name: "PS7DscSupport",
|
||||
description: "Support the cross-platform class-based DSC"),
|
||||
new ExperimentalFeature(
|
||||
name: "PSSubsystemPluginModel",
|
||||
description: "A plugin model for registering and un-registering PowerShell subsystems"),
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Generic;
|
||||
using System.Management.Automation.Language;
|
||||
|
||||
namespace System.Management.Automation.Subsystem.DSC
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for implementing a cross platform desired state configuration component.
|
||||
/// </summary>
|
||||
public interface ICrossPlatformDsc : ISubsystem
|
||||
{
|
||||
/// <summary>
|
||||
/// Subsystem kind.
|
||||
/// </summary>
|
||||
SubsystemKind ISubsystem.Kind => SubsystemKind.CrossPlatformDsc;
|
||||
|
||||
/// <summary>
|
||||
/// Default implementation. No function is required for this subsystem.
|
||||
/// </summary>
|
||||
Dictionary<string, string>? ISubsystem.FunctionsToDefine => null;
|
||||
|
||||
/// <summary>
|
||||
/// DSC initializer function.
|
||||
/// </summary>
|
||||
void LoadDefaultKeywords(Collection<Exception> errors);
|
||||
|
||||
/// <summary>
|
||||
/// Clear internal class caches.
|
||||
/// </summary>
|
||||
void ClearCache();
|
||||
|
||||
/// <summary>
|
||||
/// Returns resource usage string.
|
||||
/// </summary>
|
||||
string GetDSCResourceUsageString(DynamicKeyword keyword);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a string is one of dynamic keywords that can be used in both configuration and meta configuration.
|
||||
/// </summary>
|
||||
bool IsSystemResourceName(string name);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a string matches default module name used for meta configuration resources.
|
||||
/// </summary>
|
||||
bool IsDefaultModuleNameForMetaConfigResource(string name);
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,11 @@ namespace System.Management.Automation.Subsystem
|
||||
/// Component that provides predictive suggestions to commandline input.
|
||||
/// </summary>
|
||||
CommandPredictor = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Cross platform desired state configuration component.
|
||||
/// </summary>
|
||||
CrossPlatformDsc = 2,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -8,6 +8,7 @@ using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Management.Automation.Internal;
|
||||
using System.Management.Automation.Subsystem.DSC;
|
||||
using System.Management.Automation.Subsystem.Prediction;
|
||||
|
||||
namespace System.Management.Automation.Subsystem
|
||||
@@ -29,6 +30,11 @@ namespace System.Management.Automation.Subsystem
|
||||
SubsystemKind.CommandPredictor,
|
||||
allowUnregistration: true,
|
||||
allowMultipleRegistration: true),
|
||||
|
||||
SubsystemInfo.Create<ICrossPlatformDsc>(
|
||||
SubsystemKind.CrossPlatformDsc,
|
||||
allowUnregistration: true,
|
||||
allowMultipleRegistration: false),
|
||||
};
|
||||
|
||||
var subSystemTypeMap = new Dictionary<Type, SubsystemInfo>(subsystems.Length);
|
||||
|
||||
@@ -12,6 +12,8 @@ using System.Management.Automation.Runspaces;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
using System.Management.Automation.Subsystem;
|
||||
using System.Management.Automation.Subsystem.DSC;
|
||||
using Dsc = Microsoft.PowerShell.DesiredStateConfiguration.Internal;
|
||||
|
||||
namespace System.Management.Automation.Language
|
||||
@@ -2933,7 +2935,6 @@ namespace System.Management.Automation.Language
|
||||
//
|
||||
Runspaces.Runspace localRunspace = null;
|
||||
bool topLevel = false;
|
||||
bool useCrossPlatformSchema = false;
|
||||
try
|
||||
{
|
||||
// At this point, we'll need a runspace to use to hold the metadata for the parse. If there is no
|
||||
@@ -2996,38 +2997,13 @@ namespace System.Management.Automation.Language
|
||||
{
|
||||
// Load the default CIM keywords
|
||||
Collection<Exception> CIMKeywordErrors = new Collection<Exception>();
|
||||
if (ExperimentalFeature.IsEnabled(Dsc.CrossPlatform.DscClassCache.DscExperimentalFeatureName))
|
||||
|
||||
// DscSubsystem is auto-registered when PSDesiredStateConfiguration v3 module is loaded
|
||||
// so if DscSubsystem is registered that means user intention to use v3 APIs.
|
||||
ICrossPlatformDsc dscSubsystem = SubsystemManager.GetSubsystem<ICrossPlatformDsc>();
|
||||
if (dscSubsystem != null)
|
||||
{
|
||||
// In addition to checking if experimental feature is enabled
|
||||
// also check if PSDesiredStateConfiguration is already loaded
|
||||
// if pre-v3 is already loaded then use old mof-based APIs
|
||||
// otherwise use json-based APIs
|
||||
|
||||
p.AddCommand(new CmdletInfo("Get-Module", typeof(Microsoft.PowerShell.Commands.GetModuleCommand)));
|
||||
p.AddParameter("Name", "PSDesiredStateConfiguration");
|
||||
|
||||
bool prev3IsLoaded = false;
|
||||
foreach (PSModuleInfo moduleInfo in p.Invoke<PSModuleInfo>())
|
||||
{
|
||||
if (moduleInfo.Version.Major < 3)
|
||||
{
|
||||
prev3IsLoaded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
p.Commands.Clear();
|
||||
|
||||
useCrossPlatformSchema = !prev3IsLoaded;
|
||||
|
||||
if (useCrossPlatformSchema)
|
||||
{
|
||||
Dsc.CrossPlatform.DscClassCache.LoadDefaultCimKeywords(CIMKeywordErrors);
|
||||
}
|
||||
else
|
||||
{
|
||||
Dsc.DscClassCache.LoadDefaultCimKeywords(CIMKeywordErrors);
|
||||
}
|
||||
dscSubsystem.LoadDefaultKeywords(CIMKeywordErrors);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3274,9 +3250,10 @@ namespace System.Management.Automation.Language
|
||||
// Clear out all of the cached classes and keywords.
|
||||
// They will need to be reloaded when the generated function is actually run.
|
||||
//
|
||||
if (useCrossPlatformSchema)
|
||||
ICrossPlatformDsc dscSubsystem = SubsystemManager.GetSubsystem<ICrossPlatformDsc>();
|
||||
if (dscSubsystem != null)
|
||||
{
|
||||
Dsc.CrossPlatform.DscClassCache.ClearCache();
|
||||
dscSubsystem.ClearCache();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -11,6 +11,8 @@ using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
|
||||
using Microsoft.PowerShell;
|
||||
using System.Management.Automation.Subsystem;
|
||||
using System.Management.Automation.Subsystem.DSC;
|
||||
using Microsoft.PowerShell.DesiredStateConfiguration.Internal;
|
||||
|
||||
namespace System.Management.Automation.Language
|
||||
@@ -1405,7 +1407,10 @@ namespace System.Management.Automation.Language
|
||||
{
|
||||
StringConstantExpressionAst nameAst = dynamicKeywordStatementAst.CommandElements[0] as StringConstantExpressionAst;
|
||||
Diagnostics.Assert(nameAst != null, "nameAst should never be null");
|
||||
if (!DscClassCache.SystemResourceNames.Contains(nameAst.Extent.Text.Trim()))
|
||||
var extentText = nameAst.Extent.Text.Trim();
|
||||
ICrossPlatformDsc dscSubsystem = SubsystemManager.GetSubsystem<ICrossPlatformDsc>();
|
||||
var extentTextIsASystemResourceName = (dscSubsystem != null) ? dscSubsystem.IsSystemResourceName(extentText) : DscClassCache.SystemResourceNames.Contains(extentText);
|
||||
if (!extentTextIsASystemResourceName)
|
||||
{
|
||||
if (configAst.ConfigurationType == ConfigurationType.Meta && !dynamicKeywordStatementAst.Keyword.IsMetaDSCResource())
|
||||
{
|
||||
|
||||
@@ -12,6 +12,8 @@ using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
|
||||
using Microsoft.PowerShell.Commands;
|
||||
using System.Management.Automation.Subsystem;
|
||||
using System.Management.Automation.Subsystem.DSC;
|
||||
using Microsoft.PowerShell.DesiredStateConfiguration.Internal;
|
||||
|
||||
namespace System.Management.Automation.Language
|
||||
@@ -361,7 +363,15 @@ namespace System.Management.Automation.Language
|
||||
string implementingModule = keyword.ImplementingModule;
|
||||
if (implementingModule != null)
|
||||
{
|
||||
return implementingModule.Equals(DscClassCache.DefaultModuleInfoForMetaConfigResource.Item1, StringComparison.OrdinalIgnoreCase);
|
||||
ICrossPlatformDsc dscSubsystem = SubsystemManager.GetSubsystem<ICrossPlatformDsc>();
|
||||
if (dscSubsystem != null)
|
||||
{
|
||||
dscSubsystem.IsDefaultModuleNameForMetaConfigResource(implementingModule);
|
||||
}
|
||||
else
|
||||
{
|
||||
return implementingModule.Equals(DscClassCache.DefaultModuleInfoForMetaConfigResource.Item1, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Management.Automation.Subsystem;
|
||||
using System.Management.Automation.Subsystem.DSC;
|
||||
using System.Management.Automation.Subsystem.Prediction;
|
||||
using System.Threading;
|
||||
using Xunit;
|
||||
@@ -20,8 +21,7 @@ namespace PSTests.Sequential
|
||||
predictor2 = MyPredictor.SlowPredictor;
|
||||
}
|
||||
|
||||
// This method needs to be updated when there are more than 1 subsystem defined.
|
||||
private static void VerifySubsystemMetadata(SubsystemInfo ssInfo)
|
||||
private static void VerifyCommandPredictorMetadata(SubsystemInfo ssInfo)
|
||||
{
|
||||
Assert.Equal(SubsystemKind.CommandPredictor, ssInfo.Kind);
|
||||
Assert.Equal(typeof(ICommandPredictor), ssInfo.SubsystemType);
|
||||
@@ -31,26 +31,51 @@ namespace PSTests.Sequential
|
||||
Assert.Empty(ssInfo.RequiredFunctions);
|
||||
}
|
||||
|
||||
private static void VerifyCrossPlatformDscMetadata(SubsystemInfo ssInfo)
|
||||
{
|
||||
Assert.Equal(SubsystemKind.CrossPlatformDsc, ssInfo.Kind);
|
||||
Assert.Equal(typeof(ICrossPlatformDsc), ssInfo.SubsystemType);
|
||||
Assert.True(ssInfo.AllowUnregistration);
|
||||
Assert.False(ssInfo.AllowMultipleRegistration);
|
||||
Assert.Empty(ssInfo.RequiredCmdlets);
|
||||
Assert.Empty(ssInfo.RequiredFunctions);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void GetSubsystemInfo()
|
||||
{
|
||||
SubsystemInfo ssInfo = SubsystemManager.GetSubsystemInfo(typeof(ICommandPredictor));
|
||||
SubsystemInfo predictorInfo = SubsystemManager.GetSubsystemInfo(typeof(ICommandPredictor));
|
||||
|
||||
VerifySubsystemMetadata(ssInfo);
|
||||
Assert.False(ssInfo.IsRegistered);
|
||||
Assert.Empty(ssInfo.Implementations);
|
||||
VerifyCommandPredictorMetadata(predictorInfo);
|
||||
Assert.False(predictorInfo.IsRegistered);
|
||||
Assert.Empty(predictorInfo.Implementations);
|
||||
|
||||
SubsystemInfo ssInfo2 = SubsystemManager.GetSubsystemInfo(SubsystemKind.CommandPredictor);
|
||||
Assert.Same(ssInfo2, ssInfo);
|
||||
SubsystemInfo predictorInfo2 = SubsystemManager.GetSubsystemInfo(SubsystemKind.CommandPredictor);
|
||||
Assert.Same(predictorInfo2, predictorInfo);
|
||||
|
||||
SubsystemInfo crossPlatformDscInfo = SubsystemManager.GetSubsystemInfo(typeof(ICrossPlatformDsc));
|
||||
|
||||
VerifyCrossPlatformDscMetadata(crossPlatformDscInfo);
|
||||
Assert.False(crossPlatformDscInfo.IsRegistered);
|
||||
Assert.Empty(crossPlatformDscInfo.Implementations);
|
||||
|
||||
SubsystemInfo crossPlatformDscInfo2 = SubsystemManager.GetSubsystemInfo(SubsystemKind.CrossPlatformDsc);
|
||||
Assert.Same(crossPlatformDscInfo2, crossPlatformDscInfo);
|
||||
|
||||
ReadOnlyCollection<SubsystemInfo> ssInfos = SubsystemManager.GetAllSubsystemInfo();
|
||||
Assert.Single(ssInfos);
|
||||
Assert.Same(ssInfos[0], ssInfo);
|
||||
Assert.Equal(2, ssInfos.Count);
|
||||
Assert.Same(ssInfos[0], predictorInfo);
|
||||
Assert.Same(ssInfos[1], crossPlatformDscInfo);
|
||||
|
||||
ICommandPredictor impl = SubsystemManager.GetSubsystem<ICommandPredictor>();
|
||||
Assert.Null(impl);
|
||||
ReadOnlyCollection<ICommandPredictor> impls = SubsystemManager.GetSubsystems<ICommandPredictor>();
|
||||
Assert.Empty(impls);
|
||||
ICommandPredictor predictorImpl = SubsystemManager.GetSubsystem<ICommandPredictor>();
|
||||
Assert.Null(predictorImpl);
|
||||
ReadOnlyCollection<ICommandPredictor> predictorImpls = SubsystemManager.GetSubsystems<ICommandPredictor>();
|
||||
Assert.Empty(predictorImpls);
|
||||
|
||||
ICrossPlatformDsc crossPlatformDscImpl = SubsystemManager.GetSubsystem<ICrossPlatformDsc>();
|
||||
Assert.Null(crossPlatformDscImpl);
|
||||
ReadOnlyCollection<ICrossPlatformDsc> crossPlatformDscImpls = SubsystemManager.GetSubsystems<ICrossPlatformDsc>();
|
||||
Assert.Empty(crossPlatformDscImpls);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -73,7 +98,8 @@ namespace PSTests.Sequential
|
||||
|
||||
// Now validate the SubsystemInfo of the 'ICommandPredictor' subsystem
|
||||
SubsystemInfo ssInfo = SubsystemManager.GetSubsystemInfo(typeof(ICommandPredictor));
|
||||
VerifySubsystemMetadata(ssInfo);
|
||||
SubsystemInfo crossPlatformDscInfo = SubsystemManager.GetSubsystemInfo(typeof(ICrossPlatformDsc));
|
||||
VerifyCommandPredictorMetadata(ssInfo);
|
||||
Assert.True(ssInfo.IsRegistered);
|
||||
Assert.Single(ssInfo.Implementations);
|
||||
|
||||
@@ -85,11 +111,6 @@ namespace PSTests.Sequential
|
||||
Assert.Equal(SubsystemKind.CommandPredictor, implInfo.Kind);
|
||||
Assert.Same(typeof(MyPredictor), implInfo.ImplementationType);
|
||||
|
||||
// Now validate the all-subsystem-info collection.
|
||||
ReadOnlyCollection<SubsystemInfo> ssInfos = SubsystemManager.GetAllSubsystemInfo();
|
||||
Assert.Single(ssInfos);
|
||||
Assert.Same(ssInfos[0], ssInfo);
|
||||
|
||||
// Now validate the subsystem implementation itself.
|
||||
ICommandPredictor impl = SubsystemManager.GetSubsystem<ICommandPredictor>();
|
||||
Assert.Same(impl, predictor1);
|
||||
@@ -113,7 +134,7 @@ namespace PSTests.Sequential
|
||||
SubsystemManager.RegisterSubsystem(SubsystemKind.CommandPredictor, predictor2);
|
||||
|
||||
// Now validate the SubsystemInfo of the 'ICommandPredictor' subsystem
|
||||
VerifySubsystemMetadata(ssInfo);
|
||||
VerifyCommandPredictorMetadata(ssInfo);
|
||||
Assert.True(ssInfo.IsRegistered);
|
||||
Assert.Equal(2, ssInfo.Implementations.Count);
|
||||
|
||||
@@ -158,7 +179,7 @@ namespace PSTests.Sequential
|
||||
SubsystemManager.UnregisterSubsystem<ICommandPredictor>(predictor1.Id);
|
||||
|
||||
SubsystemInfo ssInfo = SubsystemManager.GetSubsystemInfo(SubsystemKind.CommandPredictor);
|
||||
VerifySubsystemMetadata(ssInfo);
|
||||
VerifyCommandPredictorMetadata(ssInfo);
|
||||
Assert.True(ssInfo.IsRegistered);
|
||||
Assert.Single(ssInfo.Implementations);
|
||||
|
||||
@@ -179,7 +200,7 @@ namespace PSTests.Sequential
|
||||
// Unregister 'predictor2'
|
||||
SubsystemManager.UnregisterSubsystem(SubsystemKind.CommandPredictor, predictor2.Id);
|
||||
|
||||
VerifySubsystemMetadata(ssInfo);
|
||||
VerifyCommandPredictorMetadata(ssInfo);
|
||||
Assert.False(ssInfo.IsRegistered);
|
||||
Assert.Empty(ssInfo.Implementations);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user