diff --git a/docs/testing-guidelines/testing-guidelines.md b/docs/testing-guidelines/testing-guidelines.md index d2d4d18ede..85e78234e3 100755 --- a/docs/testing-guidelines/testing-guidelines.md +++ b/docs/testing-guidelines/testing-guidelines.md @@ -90,11 +90,11 @@ Start-PSPester ``` If you wish to run specific tests, that is possible as well: ``` -Start-PSPester -Directory test/powershell/engine/Api +Start-PSPester -Path test/powershell/engine/Api ``` Or a specific Pester test file: ``` -Start-PSPester -Directory test/powershell/engine/Api -Test XmlAdapter.Tests.Api +Start-PSPester -Path test/powershell/engine/Api/XmlAdapter.Tests.ps1 ``` ### What happens after your PR? diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/CSVCommands.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/CSVCommands.cs index 377607e976..78a7825ef6 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/CSVCommands.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/CSVCommands.cs @@ -1190,11 +1190,31 @@ namespace Microsoft.PowerShell.Commands TypeName = ReadTypeInformation(); } - if ((Header == null) && (!this.EOF)) + while ((Header == null) && (!this.EOF)) { - Collection values = ParseNextRecord(true); - if (values.Count != 0) + Collection values = ParseNextRecord(); + + // Trim all trailing blankspaces and delimiters ( single/multiple ). + // If there is only one element in the row and if its a blankspace we dont trim it. + // A trailing delimiter is represented as a blankspace while being added to result collection + // which is getting trimmed along with blankspaces supplied through the CSV in the below loop. + while (values.Count > 1 && values[values.Count - 1].Equals(string.Empty)) { + values.RemoveAt(values.Count - 1); + } + + // File starts with '#' and contains '#Fields:' is W3C Extended Log File Format + if (values.Count != 0 && values[0].StartsWith("#Fields: ")) + { + values[0] = values[0].Substring(9); + Header = values; + } else if (values.Count != 0 && values[0].StartsWith("#")) + { + // Skip all lines starting with '#' + } else + { + // This is not W3C Extended Log File Format + // By default first line is Header Header = values; } } @@ -1213,7 +1233,7 @@ namespace Microsoft.PowerShell.Commands ReadHeader(); while (true) { - Collection values = ParseNextRecord(false); + Collection values = ParseNextRecord(); if (values.Count == 0) break; @@ -1300,14 +1320,11 @@ namespace Microsoft.PowerShell.Commands /// Reads the next record from the file and returns parsed collection /// of string. /// - /// - /// Indicates if the parsed row is a header row or a values row. - /// /// /// Parsed collection of strings. /// private Collection - ParseNextRecord(bool isHeaderRow) + ParseNextRecord() { //Collection of strings to return Collection result = new Collection(); @@ -1471,18 +1488,6 @@ namespace Microsoft.PowerShell.Commands result.Add(current.ToString()); } - //Trim all trailing blankspaces and delimiters ( single/multiple ). - // If there is only one element in the row and if its a blankspace we dont trim it. - // A trailing delimiter is represented as a blankspace while being added to result collection - // which is getting trimmed along with blankspaces supplied through the CSV in the below loop. - if (isHeaderRow) - { - while (result.Count > 1 && result[result.Count - 1].Equals(string.Empty)) - { - result.RemoveAt(result.Count - 1); - } - } - return result; } diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetUptime.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetUptime.cs index ab873bf42e..86d1310809 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetUptime.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetUptime.cs @@ -12,7 +12,7 @@ namespace Microsoft.PowerShell.Commands /// /// This class implements Get-Uptime /// - [Cmdlet(VerbsCommon.Get, "Uptime", DefaultParameterSetName = TimespanParameterSet, HelpUri = "")] + [Cmdlet(VerbsCommon.Get, "Uptime", DefaultParameterSetName = TimespanParameterSet, HelpUri = "https://go.microsoft.com/fwlink/?linkid=834862")] [OutputType(typeof(TimeSpan), ParameterSetName = new string[] { TimespanParameterSet })] [OutputType(typeof(DateTime), ParameterSetName = new string[] { SinceParameterSet })] public class GetUptimeCommand : PSCmdlet diff --git a/src/System.Management.Automation/commands/utility/FormatAndOutput/common/DisplayDatabase/displayDescriptionData_List.cs b/src/System.Management.Automation/commands/utility/FormatAndOutput/common/DisplayDatabase/displayDescriptionData_List.cs index 436ba7b894..e62c649aa8 100644 --- a/src/System.Management.Automation/commands/utility/FormatAndOutput/common/DisplayDatabase/displayDescriptionData_List.cs +++ b/src/System.Management.Automation/commands/utility/FormatAndOutput/common/DisplayDatabase/displayDescriptionData_List.cs @@ -349,7 +349,7 @@ namespace System.Management.Automation internal bool SafeForExport() { return DisplayEntry.SafeForExport() && - ItemSelectionCondition == null || ItemSelectionCondition.SafeForExport(); + (ItemSelectionCondition == null || ItemSelectionCondition.SafeForExport()); } internal bool CompatibleWithOldPowerShell() diff --git a/src/System.Management.Automation/commands/utility/FormatAndOutput/common/DisplayDatabase/displayDescriptionData_Wide.cs b/src/System.Management.Automation/commands/utility/FormatAndOutput/common/DisplayDatabase/displayDescriptionData_Wide.cs index 660271fbcb..4e25bb280a 100644 --- a/src/System.Management.Automation/commands/utility/FormatAndOutput/common/DisplayDatabase/displayDescriptionData_Wide.cs +++ b/src/System.Management.Automation/commands/utility/FormatAndOutput/common/DisplayDatabase/displayDescriptionData_Wide.cs @@ -244,7 +244,7 @@ namespace System.Management.Automation internal bool SafeForExport() { - return DisplayEntry.SafeForExport() && EntrySelectedBy == null || EntrySelectedBy.SafeForExport(); + return DisplayEntry.SafeForExport() && (EntrySelectedBy == null || EntrySelectedBy.SafeForExport()); } internal bool CompatibleWithOldPowerShell() diff --git a/src/System.Management.Automation/commands/utility/FormatAndOutput/common/FormatViewGenerator_Complex.cs b/src/System.Management.Automation/commands/utility/FormatAndOutput/common/FormatViewGenerator_Complex.cs index 81ce6cea20..c01c363db1 100644 --- a/src/System.Management.Automation/commands/utility/FormatAndOutput/common/FormatViewGenerator_Complex.cs +++ b/src/System.Management.Automation/commands/utility/FormatAndOutput/common/FormatViewGenerator_Complex.cs @@ -433,8 +433,7 @@ namespace Microsoft.PowerShell.Commands.Internal.Format TraversalInfo level = new TraversalInfo(0, maxDepth); List mshParameterList = null; - if (inputParameters != null) - mshParameterList = inputParameters.mshParameterList; + mshParameterList = inputParameters.mshParameterList; // create a top level entry as root of the tree ComplexViewEntry cve = new ComplexViewEntry(); diff --git a/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs b/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs index 1c9256e4c2..6a6769fc51 100644 --- a/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs +++ b/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs @@ -5860,7 +5860,17 @@ namespace System.Management.Automation #region Process_LoadedAssemblies var assembliesExcludingPSGenerated = ClrFacade.GetAssemblies(); - var allPublicTypes = assembliesExcludingPSGenerated.SelectMany(assembly => assembly.GetTypes().Where(TypeResolver.IsPublic)); + var allPublicTypes = assembliesExcludingPSGenerated.SelectMany(assembly => + { + try + { + return assembly.GetTypes().Where(TypeResolver.IsPublic); + } + catch (ReflectionTypeLoadException) + { + } + return Type.EmptyTypes; + }); foreach (var type in allPublicTypes) { diff --git a/src/System.Management.Automation/engine/CommandMetadata.cs b/src/System.Management.Automation/engine/CommandMetadata.cs index b3502b598d..fc57bf4755 100644 --- a/src/System.Management.Automation/engine/CommandMetadata.cs +++ b/src/System.Management.Automation/engine/CommandMetadata.cs @@ -189,12 +189,9 @@ namespace System.Management.Automation _parameters = new Dictionary(other.Parameters.Count, StringComparer.OrdinalIgnoreCase); // deep copy - if (other.Parameters != null) + foreach (KeyValuePair entry in other.Parameters) { - foreach (KeyValuePair entry in other.Parameters) - { - _parameters.Add(entry.Key, new ParameterMetadata(entry.Value)); - } + _parameters.Add(entry.Key, new ParameterMetadata(entry.Value)); } // deep copy of the collection, collection items (Attributes) copied by reference diff --git a/src/System.Management.Automation/engine/ErrorPackage.cs b/src/System.Management.Automation/engine/ErrorPackage.cs index f78eb8ee66..b8edf4f060 100644 --- a/src/System.Management.Automation/engine/ErrorPackage.cs +++ b/src/System.Management.Automation/engine/ErrorPackage.cs @@ -1129,7 +1129,7 @@ namespace System.Management.Automation { PopulateProperties(exception, targetObject, fullyQualifiedErrorId, errorCategory, errorCategory_Activity, errorCategory_Reason, errorCategory_TargetName, errorCategory_TargetType, - errorDetails_Message, errorDetails_Message, errorDetails_RecommendedAction, null); + errorCategory_Message, errorDetails_Message, errorDetails_RecommendedAction, null); } private void PopulateProperties(Exception exception, diff --git a/src/System.Management.Automation/engine/Modules/ImportModuleCommand.cs b/src/System.Management.Automation/engine/Modules/ImportModuleCommand.cs index acabd4f007..0382232a37 100644 --- a/src/System.Management.Automation/engine/Modules/ImportModuleCommand.cs +++ b/src/System.Management.Automation/engine/Modules/ImportModuleCommand.cs @@ -1660,7 +1660,7 @@ namespace Microsoft.PowerShell.Commands /// protected override void ProcessRecord() { - if (BaseMaximumVersion != null && BaseMaximumVersion != null && BaseMaximumVersion < BaseMinimumVersion) + if (BaseMaximumVersion != null && BaseMinimumVersion != null && BaseMaximumVersion < BaseMinimumVersion) { string message = StringUtil.Format(Modules.MinimumVersionAndMaximumVersionInvalidRange, BaseMinimumVersion, BaseMaximumVersion); throw new PSArgumentOutOfRangeException(message); diff --git a/src/System.Management.Automation/engine/SessionStateProviderAPIs.cs b/src/System.Management.Automation/engine/SessionStateProviderAPIs.cs index 3ef80291a7..2196458f4b 100644 --- a/src/System.Management.Automation/engine/SessionStateProviderAPIs.cs +++ b/src/System.Management.Automation/engine/SessionStateProviderAPIs.cs @@ -1001,7 +1001,7 @@ namespace System.Management.Automation { ProviderNotFoundException e = new ProviderNotFoundException( - providerName.ToString(), + "null", SessionStateCategory.CmdletProvider, "ProviderNotFound", SessionStateStrings.ProviderNotFound); diff --git a/src/System.Management.Automation/engine/hostifaces/RunspacePoolInternal.cs b/src/System.Management.Automation/engine/hostifaces/RunspacePoolInternal.cs index c332583fe8..fd65d9f59c 100644 --- a/src/System.Management.Automation/engine/hostifaces/RunspacePoolInternal.cs +++ b/src/System.Management.Automation/engine/hostifaces/RunspacePoolInternal.cs @@ -574,14 +574,14 @@ namespace System.Management.Automation.Runspaces.Internal int unUsedCapacity = (maxPoolSz - totalRunspaces) < 0 ? 0 : (maxPoolSz - totalRunspaces); return (pool.Count + unUsedCapacity); } - else if (stateInfo.State != RunspacePoolState.BeforeOpen && stateInfo.State != RunspacePoolState.Opening) - { - throw new InvalidOperationException(HostInterfaceExceptionsStrings.RunspacePoolNotOpened); - } else if (stateInfo.State == RunspacePoolState.Disconnected) { throw new InvalidOperationException(RunspacePoolStrings.CannotWhileDisconnected); } + else if (stateInfo.State != RunspacePoolState.BeforeOpen && stateInfo.State != RunspacePoolState.Opening) + { + throw new InvalidOperationException(HostInterfaceExceptionsStrings.RunspacePoolNotOpened); + } else { return maxPoolSz; diff --git a/src/System.Management.Automation/engine/parser/Parser.cs b/src/System.Management.Automation/engine/parser/Parser.cs index 7ebedd8cc7..1310b24952 100644 --- a/src/System.Management.Automation/engine/parser/Parser.cs +++ b/src/System.Management.Automation/engine/parser/Parser.cs @@ -4311,23 +4311,33 @@ namespace System.Management.Automation.Language IScriptExtent endExtent = enumeratorName.Extent; ExpressionAst initialValueAst = null; - var assignToken = PeekToken(); var missingInitializer = false; - if (assignToken.Kind == TokenKind.Equals) + var oldTokenizerMode = _tokenizer.Mode; + Token assignToken = null; + try { - SkipToken(); - initialValueAst = ExpressionRule(); - if (initialValueAst == null) + SetTokenizerMode(TokenizerMode.Expression); + assignToken = PeekToken(); + if (assignToken.Kind == TokenKind.Equals) { - ReportError(After(assignToken), () => ParserStrings.ExpectedValueExpression, assignToken.Kind.Text()); - endExtent = assignToken.Extent; - missingInitializer = true; - } - else - { - endExtent = initialValueAst.Extent; + SkipToken(); + initialValueAst = ExpressionRule(); + if (initialValueAst == null) + { + ReportError(After(assignToken), () => ParserStrings.ExpectedValueExpression, assignToken.Kind.Text()); + endExtent = assignToken.Extent; + missingInitializer = true; + } + else + { + endExtent = initialValueAst.Extent; + } } } + finally + { + SetTokenizerMode(oldTokenizerMode); + } Token terminatorToken = PeekToken(); if (terminatorToken.Kind != TokenKind.NewLine && terminatorToken.Kind != TokenKind.Semi && terminatorToken.Kind != TokenKind.RCurly) @@ -4970,9 +4980,8 @@ namespace System.Management.Automation.Language } else { - errorAsts.Concat(exceptionTypes); + errorAsts.AddRange(exceptionTypes); } - // REVIEW: seems like some code is missing here, errorAsts isn't used } return null; } diff --git a/src/System.Management.Automation/engine/remoting/client/Job.cs b/src/System.Management.Automation/engine/remoting/client/Job.cs index ff3162e9d6..913d8587c7 100644 --- a/src/System.Management.Automation/engine/remoting/client/Job.cs +++ b/src/System.Management.Automation/engine/remoting/client/Job.cs @@ -1873,7 +1873,7 @@ namespace System.Management.Automation foreach (Job j in ChildJobs) { PSRemotingChildJob child = j as PSRemotingChildJob; - if (j == null) continue; + if (child == null) continue; if (String.Equals(child.Runspace.ConnectionInfo.ComputerName, computerName, StringComparison.OrdinalIgnoreCase)) { @@ -1897,7 +1897,7 @@ namespace System.Management.Automation foreach (Job j in ChildJobs) { PSRemotingChildJob child = j as PSRemotingChildJob; - if (j == null) continue; + if (child == null) continue; if (child.Runspace.InstanceId.Equals(runspace.InstanceId)) { returnJobList.Add(child); @@ -1920,7 +1920,7 @@ namespace System.Management.Automation foreach (Job j in ChildJobs) { PSRemotingChildJob child = j as PSRemotingChildJob; - if (j == null) continue; + if (child == null) continue; if (child.Helper.Equals(helper)) { returnJobList.Add(child); diff --git a/src/System.Management.Automation/engine/remoting/server/serverremotesession.cs b/src/System.Management.Automation/engine/remoting/server/serverremotesession.cs index 25fc3d3233..9157455b35 100644 --- a/src/System.Management.Automation/engine/remoting/server/serverremotesession.cs +++ b/src/System.Management.Automation/engine/remoting/server/serverremotesession.cs @@ -630,7 +630,7 @@ namespace System.Management.Automation.Remoting int clientRequestedMinRunspaces = -1; int clientRequestedMaxRunspaces = -1; bool clientRequestedRunspaceCount = false; - if (connectRunspacePoolObject.Data.Properties[RemoteDataNameStrings.MinRunspaces] != null && connectRunspacePoolObject.Data.Properties[RemoteDataNameStrings.MinRunspaces] != null) + if (connectRunspacePoolObject.Data.Properties[RemoteDataNameStrings.MinRunspaces] != null && connectRunspacePoolObject.Data.Properties[RemoteDataNameStrings.MaxRunspaces] != null) { try { diff --git a/src/System.Management.Automation/namespaces/FileSystemProvider.cs b/src/System.Management.Automation/namespaces/FileSystemProvider.cs index 8e94801295..607ef6e47c 100644 --- a/src/System.Management.Automation/namespaces/FileSystemProvider.cs +++ b/src/System.Management.Automation/namespaces/FileSystemProvider.cs @@ -4125,7 +4125,7 @@ namespace Microsoft.PowerShell.Commands { // Check if the remote source file has any alternate data streams ArrayList remoteFileStreams = GetRemoteSourceAlternateStreams(ps, sourceFileFullName); - if ((remoteFileStreams.Count > 0) && (remoteFileStreams != null)) + if ((remoteFileStreams != null) && (remoteFileStreams.Count > 0)) { foreach (string streamName in remoteFileStreams) { diff --git a/src/System.Management.Automation/utils/PowerShellETWTracer.cs b/src/System.Management.Automation/utils/PowerShellETWTracer.cs index b853d751d4..ad27026a80 100644 --- a/src/System.Management.Automation/utils/PowerShellETWTracer.cs +++ b/src/System.Management.Automation/utils/PowerShellETWTracer.cs @@ -1085,7 +1085,7 @@ namespace System.Management.Automation.Tracing { return DebugChannel.TraceDebug(PowerShellTraceEvent.Job, PowerShellTraceOperationCode.Method, PowerShellTraceTask.None, - job.Id.ToString(CultureInfo.InvariantCulture), job.InstanceId.ToString(), "NULL job"); + "", "", "NULL job"); } } diff --git a/src/libpsl-native/src/getcurrentthreadid.cpp b/src/libpsl-native/src/getcurrentthreadid.cpp index e836685ccd..84d5b6f4ae 100644 --- a/src/libpsl-native/src/getcurrentthreadid.cpp +++ b/src/libpsl-native/src/getcurrentthreadid.cpp @@ -3,6 +3,7 @@ #include #include #include +#include pid_t GetCurrentThreadId() { @@ -10,7 +11,9 @@ pid_t GetCurrentThreadId() #if defined(__linux__) tid = syscall(SYS_gettid); #elif defined(__APPLE__) && defined(__MACH__) - tid = syscall(SYS_thread_selfid); + uint64_t tid64; + pthread_threadid_np(NULL, &tid64); + tid = (pid_t)tid64; #endif return tid; } diff --git a/src/vs-csproj/Microsoft.PowerShell.Commands.Utility.csproj b/src/vs-csproj/Microsoft.PowerShell.Commands.Utility.csproj index f0a75c8a5a..7513116c53 100644 --- a/src/vs-csproj/Microsoft.PowerShell.Commands.Utility.csproj +++ b/src/vs-csproj/Microsoft.PowerShell.Commands.Utility.csproj @@ -193,6 +193,9 @@ commands\utility\GetUnique.cs + + commands\utility\GetUptime.cs + commands\utility\group-object.cs @@ -694,4 +697,4 @@ - \ No newline at end of file + diff --git a/test/powershell/Language/Classes/scripting.enums.tests.ps1 b/test/powershell/Language/Classes/scripting.enums.tests.ps1 index fbca0604c0..f13b31be47 100644 --- a/test/powershell/Language/Classes/scripting.enums.tests.ps1 +++ b/test/powershell/Language/Classes/scripting.enums.tests.ps1 @@ -3,7 +3,6 @@ # Describe 'enums' -Tags "CI" { - Context 'basic enums' { enum E1 { @@ -62,9 +61,10 @@ Describe 'enums' -Tags "CI" { e0 = [E6]::e0 + 2 } + # Don't add space after 'e0 ='! Fix #2543 enum E6 { - e0 = 38 + e0 =38 } It 'E4 has correct value' { [E4]::e0 | Should Be ([E4]42) } diff --git a/test/powershell/Modules/CimCmdlets/CimInstance.Tests.ps1 b/test/powershell/Modules/CimCmdlets/CimInstance.Tests.ps1 new file mode 100644 index 0000000000..db5a5a32c2 --- /dev/null +++ b/test/powershell/Modules/CimCmdlets/CimInstance.Tests.ps1 @@ -0,0 +1,41 @@ +Try { + if ( ! $IsWindows ) { + $PSDefaultParameterValues['it:pending'] = $true + } + Describe "CimInstance cmdlet tests" -Tag @("CI") { + BeforeAll { + if ( ! $IsWindows ) { return } + $instance = get-ciminstance cim_computersystem + } + It "CimClass property should not be null" { + # we can't use equals here as on windows cimclassname + # is win32_computersystem, but that's not likely to be the + # case on non-Windows systems + $instance.cimClass.CimClassName | should match _computersystem + } + It "Property access should be case insensitive" { + foreach($property in $instance.psobject.properties.name) { + $pUpper = $property.ToUpper() + $pLower = $property.ToLower() + [string]$pLowerValue = $pinstance.$pLower -join "," + [string]$pUpperValue = $pinstance.$pUpper -join "," + $pLowerValue | should be $pUpperValue + } + } + It "GetCimSessionInstanceId method invocation should return data" { + $instance.GetCimSessionInstanceId() | Should BeOfType "Guid" + } + It "should produce an error for a non-existing classname" { + try { + get-ciminstance -classname thisnameshouldnotexist -ea stop + throw "expected error did not occur" + } + catch { + $_.FullyQualifiedErrorId | should be "HRESULT 0x80041010,Microsoft.Management.Infrastructure.CimCmdlets.GetCimInstanceCommand" + } + } + } +} +finally { + $PSDefaultParameterValues.Remove('it:pending') +} diff --git a/test/powershell/Modules/CimCmdlets/CimSession.Tests.ps1 b/test/powershell/Modules/CimCmdlets/CimSession.Tests.ps1 new file mode 100644 index 0000000000..c60063f17a --- /dev/null +++ b/test/powershell/Modules/CimCmdlets/CimSession.Tests.ps1 @@ -0,0 +1,44 @@ +try { + if ( ! $IsWindows ) { + $PSDefaultParameterValues['it:pending'] = $true + } + Describe "New-CimSession" -Tag @("CI") { + BeforeAll { + $sessions = @() + } + AfterEach { + try { + $sessions | remove-cimsession + } + finally { + $sessions = @() + } + } + It "A cim session can be created" { + $sessionName = [guid]::NewGuid() + $session = New-CimSession -ComputerName . -name $sessionName + $sessions += $session + $session.Name | Should be $sessionName + $session.InstanceId | should BeOfType "System.Guid" + } + It "A Cim session can be retrieved" { + $sessionName = [guid]::NewGuid() + $session = New-CimSession -ComputerName . -name $sessionName + $sessions += $session + (get-cimsession -Name $sessionName).InstanceId | should be $session.InstanceId + (get-cimsession -Id $session.Id).InstanceId | should be $session.InstanceId + (get-cimsession -InstanceId $session.InstanceId).InstanceId | should be $session.InstanceId + } + It "A cim session can be removed" { + $sessionName = [guid]::NewGuid() + $session = New-CimSession -ComputerName . -name $sessionName + $sessions += $session + $session.Name | Should be $sessionName + $session | Remove-CimSession + Get-CimSession $session.Id -ErrorAction SilentlyContinue | should BeNullOrEmpty + } + } +} +finally { + $PSDefaultParameterValues.remove('it:pending') +} diff --git a/test/powershell/Modules/CimCmdlets/Get-CimClass.Tests.ps1 b/test/powershell/Modules/CimCmdlets/Get-CimClass.Tests.ps1 index f6a48089ce..0751cf9d86 100644 --- a/test/powershell/Modules/CimCmdlets/Get-CimClass.Tests.ps1 +++ b/test/powershell/Modules/CimCmdlets/Get-CimClass.Tests.ps1 @@ -1,6 +1,44 @@ -Describe 'Get-CimClass' -tags "CI" { - # Get-CimClass works only on windows - It 'can get CIM_Error CIM class' -Skip:(-not $IsWindows) { - Get-CimClass -ClassName CIM_Error | Should Not Be $null +try { + # Get-CimClass works only on windows right now + if ( ! $IsWindows ) { + $PSDefaultParameterValues['it:pending'] = $true } -} + + Describe 'Get-CimClass' -tags "CI" { + It 'can get CIM_Error CIM class' { + Get-CimClass -ClassName CIM_Error | Should Not BeNullOrEmpty + } + It 'can get class when namespace is specified' { + Get-CimClass -ClassName CIM_OperatingSystem -Namespace root/cimv2 | Should Not BeNullOrEmpty + } + + It 'produces an error when a non-existent class is used' { + try { + Get-CimClass -ClassName thisclasstypedoesnotexist -ea stop + throw "Expected error did not occur" + } + catch { + $_.FullyQualifiedErrorId | should be "HRESULT 0x80041002,Microsoft.Management.Infrastructure.CimCmdlets.GetCimClassCommand" + } + } + It 'produces an error when an improper namespace is used' { + try { + Get-CimClass -ClassName CIM_OperatingSystem -Namespace badnamespace -ea stop + throw "Expected error did not occur" + } + catch { + $_.FullyQualifiedErrorId | should be "HRESULT 0x8004100e,Microsoft.Management.Infrastructure.CimCmdlets.GetCimClassCommand" + } + } + } + + # feature tests + Describe 'Get-CimClass' -tags @("Feature") { + It 'can retrieve a class when a method is provided' { + Get-CimClass -MethodName Reboot | Should Not BeNullOrEmpty + } + } +} +finally { + $PSDefaultParameterValues.Remove('it:pending') +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Add-Type.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Add-Type.Tests.ps1 index ee0f2c951c..5b4b7d7d6e 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Add-Type.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Add-Type.Tests.ps1 @@ -1,11 +1,11 @@ $guid = [Guid]::NewGuid().ToString().Replace("-","") Describe "Add-Type" -Tags "CI" { - It "Should not throw given a simple class definition" -pending:($IsCoreCLR) { + It "Should not throw given a simple class definition" { { Add-Type -TypeDefinition "public static class foo { }" } | Should Not Throw } - It "Can use System.Management.Automation.CmdletAttribute" -pending:($IsCoreCLR) { + It "Can use System.Management.Automation.CmdletAttribute" { $code = @" [System.Management.Automation.Cmdlet("Get", "Thing", ConfirmImpact = System.Management.Automation.ConfirmImpact.High, SupportsPaging = true)] public class AttributeTest$guid {} @@ -13,7 +13,7 @@ public class AttributeTest$guid {} Add-Type -TypeDefinition $code -PassThru | Should Not Be $null } - It "Can load TPA assembly System.Runtime.Serialization.Primitives.dll" -pending:($IsCoreCLR) { + It "Can load TPA assembly System.Runtime.Serialization.Primitives.dll" { Add-Type -AssemblyName 'System.Runtime.Serialization.Primitives' -PassThru | Should Not Be $null } } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Import-Csv.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Import-Csv.Tests.ps1 index ff8290d97d..11f6f099f3 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Import-Csv.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Import-Csv.Tests.ps1 @@ -1,55 +1,3 @@ -Describe "Import-Csv" -Tags "CI" { - $testCsv = Join-Path -Path (Join-Path $PSScriptRoot -ChildPath assets) -ChildPath TestCsv.csv - - It "Should be able to call without error" { - { Import-Csv $testCsv } | Should Not Throw - } - - It "Should be able to assign to a variable" { - $actual = Import-Csv $testCsv - - $actual | Should Not BeNullOrEmpty - $actual.GetType().BaseType | Should Be array - } - - It "Should have the data from the csv file" { - $actualContent = $(Get-Content $testCsv)[0] - $testContent = $($(Import-Csv $testCsv) | Get-Member) | ? { $_.MemberType -eq "NoteProperty" } | % { $_.Name } | Select-Object -First 1 - - $actualContent.IndexOf($testContent) | Should BeGreaterThan -1 - } - - It "Should be able to prepend a custom header" { - $header = "test1","test2","test3" - - $originalContent = $($(Import-Csv $testCsv) | Get-Member) | ? { $_.MemberType -eq "NoteProperty" } | % { $_.Name } | Select-Object -First 1 - - $testContent = $($(Import-Csv $testCsv -Header $header) | Get-Member) | ? { $_.MemberType -eq "NoteProperty" } | % { $_.Name } | Select-Object -First 3 - - # the original csv file doesn't contain the headers - $originalContent.IndexOf($header[0]) | Should Be -1 - - # but it does with the -Header switch! - $testContent[0] | Should Be $header[0] - $testContent[1] | Should Be $header[1] - $testContent[2] | Should Be $header[2] - } - - It "Should be able to use the alias without error" { - { Import-Csv $testCsv } | Should Not Throw - } - - It "Should have the same output between the alias and the full cmdlet name" { - $alias = $($(ipcsv $testCsv) | Get-Member) | ? { $_.MemberType -eq "NoteProperty" } | % { $_.Name } | Select-Object -First 1 - $cmdlet = $($(Import-Csv $testCsv) | Get-Member) | ? { $_.MemberType -eq "NoteProperty" } | % { $_.Name } | Select-Object -First 1 - - $alias[0] | Should Be $cmdlet[0] - $alias[1] | Should Be $cmdlet[1] - $alias[2] | Should Be $cmdlet[2] - - } -} - Describe "Import-Csv DRT Unit Tests" -Tags "CI" { BeforeAll { $fileToGenerate = Join-Path $TestDrive -ChildPath "importCSVTest.csv" @@ -71,3 +19,77 @@ Describe "Import-Csv DRT Unit Tests" -Tags "CI" { $returnObject.Second | Should Be 2 } } + +Describe "Import-Csv File Format Tests" -Tags "CI" { + BeforeAll { + # The file is w/o header + $TestImportCsv_NoHeader = Join-Path -Path (Join-Path $PSScriptRoot -ChildPath assets) -ChildPath TestImportCsv_NoHeader.csv + # The file is with header + $TestImportCsv_WithHeader = Join-Path -Path (Join-Path $PSScriptRoot -ChildPath assets) -ChildPath TestImportCsv_WithHeader.csv + # The file is W3C Extended Log File Format + $TestImportCsv_W3C_ELF = Join-Path -Path (Join-Path $PSScriptRoot -ChildPath assets) -ChildPath TestImportCsv_W3C_ELF.csv + + $testCSVfiles = $TestImportCsv_NoHeader, $TestImportCsv_WithHeader, $TestImportCsv_W3C_ELF + $orginalHeader = "Column1","Column2","Column 3" + $customHeader = "test1","test2","test3" + } + # Test set is the same for all file formats + foreach ($testCsv in $testCSVfiles) { + $FileName = (dir $testCsv).Name + Context "Next test file: $FileName" { + BeforeAll { + $CustomHeaderParams = @{Header = $customHeader; Delimiter = ","} + if ($FileName -eq "TestImportCsv_NoHeader.csv") { + # The file does not have header + # (w/o Delimiter here we get throw (bug?)) + $HeaderParams = @{Header = $orginalHeader; Delimiter = ","} + } else { + # The files have header + $HeaderParams = @{Delimiter = ","} + } + + } + + It "Should be able to import all fields" { + $actual = Import-Csv -Path $testCsv @HeaderParams + $actualfields = $actual[0].psobject.Properties.Name + $actualfields | Should Be $orginalHeader + } + + It "Should be able to import all fields with custom header" { + $actual = Import-Csv -Path $testCsv @CustomHeaderParams + $actualfields = $actual[0].psobject.Properties.Name + $actualfields | Should Be $customHeader + } + + It "Should be able to import correct values" { + $actual = Import-Csv -Path $testCsv @HeaderParams + $actual.count | Should Be 4 + $actual[0].'Column1' | Should Be "data1" + $actual[0].'Column2' | Should Be "1" + $actual[0].'Column 3' | Should Be "A" + } + + } + } +} + +Describe "Import-Csv #Type Tests" -Tags "CI" { + BeforeAll { + $testfile = Join-Path $TestDrive -ChildPath "testfile.csv" + Remove-Item -Path $testfile -Force -ErrorAction SilentlyContinue + $processlist = (Get-Process)[0..1] + $processlist | Export-Csv -Path $testfile -Force + # Import-Csv add "CSV:" before actual type + # (Why #HandleCount ? See Issue #1812) + $expectedProcessType = "CSV:System.Diagnostics.Process#HandleCount" + } + + It "Test import-csv import Object" { + $importObjectList = Import-Csv -Path $testfile + $processlist.Count | Should Be $importObjectList.Count + + $importType = $importObjectList[0].psobject.TypeNames[0] + $importType | Should Be $expectedProcessType + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/assets/TestImportCsv_NoHeader.csv b/test/powershell/Modules/Microsoft.PowerShell.Utility/assets/TestImportCsv_NoHeader.csv new file mode 100644 index 0000000000..192b997de1 --- /dev/null +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/assets/TestImportCsv_NoHeader.csv @@ -0,0 +1,4 @@ +data1,1,A +data2,2,B +data3,3,C +data4,4,D diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/assets/TestImportCsv_W3C_ELF.csv b/test/powershell/Modules/Microsoft.PowerShell.Utility/assets/TestImportCsv_W3C_ELF.csv new file mode 100644 index 0000000000..e1f13f3406 --- /dev/null +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/assets/TestImportCsv_W3C_ELF.csv @@ -0,0 +1,9 @@ +#Software: Microsoft Exchange Server +#Version: 15.0.0.0 +#Log-type: Transport Connectivity Log +#Date: 2016-09-16T23:30:07.338Z +#Fields: Column1,Column2,Column 3 +data1,1,A +data2,2,B +data3,3,C +data4,4,D diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/assets/TestCsv.csv b/test/powershell/Modules/Microsoft.PowerShell.Utility/assets/TestImportCsv_WithHeader.csv similarity index 78% rename from test/powershell/Modules/Microsoft.PowerShell.Utility/assets/TestCsv.csv rename to test/powershell/Modules/Microsoft.PowerShell.Utility/assets/TestImportCsv_WithHeader.csv index 73a63d8992..1517b02299 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/assets/TestCsv.csv +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/assets/TestImportCsv_WithHeader.csv @@ -1,5 +1,6 @@ -Column1,Column2,Column 3 -data1,1,A -data2,2,B -data3,3,C -data4,4,D +# Test comment +Column1,Column2,Column 3 +data1,1,A +data2,2,B +data3,3,C +data4,4,D diff --git a/test/powershell/engine/ETS/CimAdapter.Tests.ps1 b/test/powershell/engine/ETS/CimAdapter.Tests.ps1 new file mode 100644 index 0000000000..c267ca51a4 --- /dev/null +++ b/test/powershell/engine/ETS/CimAdapter.Tests.ps1 @@ -0,0 +1,90 @@ +function getIndex +{ + param([string[]]$strings,[string]$pattern) + for ($i = 0; $i -lt $strings.Count; $i++) { + if ($strings[$i] -like $pattern) { + return $i + } + } + return -1 +} + +try { + if ( ! $IsWindows ) { + $PSDefaultParameterValues["it:pending"] = $true + } + Describe "CIM Objects are adapted properly" -Tag @("CI") { + BeforeAll { + if ( ! $IsWindows ) { + return + } + $p = get-ciminstance win32_process |Select-object -first 1 + + $indexOf_namespaceQualified_Win32Process = getIndex $p.PSTypeNames "*root?cimv2?Win32_Process" + $indexOf_namespaceQualified_CimProcess = getIndex $p.PSTypeNames "*root?cimv2?CIM_Process" + $indexOf_namespaceQualified_CimLogicalElement = getIndex $p.PSTypeNames "*root?cimv2?CIM_LogicalElement" + $indexOf_namespaceQualified_CimManagedSystemElement = getIndex $p.PSTypeNames "*root?cimv2?CIM_ManagedSystemElement" + + $indexOf_className_Win32Process = getIndex $p.PSTypeNames "*#Win32_Process" + $indexOf_className_CimProcess = getIndex $p.PSTypeNames "*#CIM_Process" + $indexOf_className_CimLogicalElement = getIndex $p.PSTypeNames "*#CIM_LogicalElement" + $indexOf_className_CimManagedSystemElement = getIndex $p.PSTypeNames "*#CIM_ManagedSystemElement" + } + AfterAll { + $PSDefaultParameterValues.Remove("it:pending") + } + + It "Namespace-qualified Win32_Process is present" -skip:(!$IsWindows) { + $indexOf_namespaceQualified_Win32Process |Should not Be (-1) + } + It "Namespace-qualified CIM_Process is present" { + $indexOf_namespaceQualified_CimProcess |Should not Be (-1) + } + It "Namespace-qualified CIM_LogicalElement is present" { + $indexOf_namespaceQualified_CimLogicalElement |Should not Be (-1) + } + It "Namespace-qualified CIM_ManagedSystemElement is present" { + $indexOf_namespaceQualified_CimManagedSystemElement |Should not Be (-1) + } + + It "Classname of Win32_Process is present" -skip:(!$IsWindows) { + $indexOf_className_Win32Process |Should not Be (-1) + } + It "Classname of CIM_Process is present" { + $indexOf_className_CimProcess |Should not Be (-1) + } + It "Classname of CIM_LogicalElement is present" { + $indexOf_className_CimLogicalElement |Should not Be (-1) + } + It "Classname of CIM_ManagedSystemElement is present" { + $indexOf_className_CimManagedSystemElement |Should not Be (-1) + } + + It "Win32_Process comes after CIM_Process (namespace qualified)" -skip:(!$IsWindows) { + $indexOf_namespaceQualified_Win32Process |should belessthan $indexOf_namespaceQualified_CimProcess + } + It "CIM_Process comes after CIM_LogicalElement (namespace qualified)" { + $indexOf_namespaceQualified_CimProcess |should belessthan $indexOf_namespaceQualified_CimLogicalElement + } + It "CIM_LogicalElement comes after CIM_ManagedSystemElement (namespace qualified)" { + $indexOf_namespaceQualified_CimLogicalElement |should belessthan $indexOf_namespaceQualified_CimManagedSystemElement + } + + It "Win32_Process comes after CIM_Process (classname only)" -skip:(!$IsWindows) { + $indexOf_className_Win32Process |should belessthan $indexOf_className_CimProcess + } + It "CIM_Process comes after CIM_LogicalElement (classname only)" { + $indexOf_className_CimProcess |should belessthan $indexOf_className_CimLogicalElement + } + It "CIM_LogicalElement comes after CIM_ManagedSystemElement (classname only)" { + $indexOf_className_CimLogicalElement |should belessthan $indexOf_className_CimManagedSystemElement + } + + It "Namespace qualified PSTypenames comes after class-only PSTypeNames" -skip:(!$IsWindows) { + $indexOf_namespaceQualified_CimManagedSystemElement |should belessthan $indexOf_className_Win32Process + } + } +} +finally { + $PSDefaultParameterValues.Remove("it:pending") +} diff --git a/test/powershell/engine/Help/assets/HelpURI/V3Cmdlets.csv b/test/powershell/engine/Help/assets/HelpURI/V3Cmdlets.csv index cbc2c68e08..71f9f3e773 100644 --- a/test/powershell/engine/Help/assets/HelpURI/V3Cmdlets.csv +++ b/test/powershell/engine/Help/assets/HelpURI/V3Cmdlets.csv @@ -89,4 +89,5 @@ New-FileCatalog,https://go.microsoft.com/fwlink/?LinkId=786749 Test-FileCatalog,https://go.microsoft.com/fwlink/?LinkId=786750 Get-ComputerInfo,https://go.microsoft.com/fwlink/?LinkId=799466 Get-TimeZone,https://go.microsoft.com/fwlink/?LinkId=799468 -Set-TimeZone,https://go.microsoft.com/fwlink/?LinkId=799469 \ No newline at end of file +Set-TimeZone,https://go.microsoft.com/fwlink/?LinkId=799469 +Get-Uptime,https://go.microsoft.com/fwlink/?linkid=834862 diff --git a/test/powershell/engine/Remoting/SessionOption.Tests.ps1 b/test/powershell/engine/Remoting/SessionOption.Tests.ps1 new file mode 100644 index 0000000000..f0431b5649 --- /dev/null +++ b/test/powershell/engine/Remoting/SessionOption.Tests.ps1 @@ -0,0 +1,54 @@ +try { + if ( ! $IsWindows ) { + $PSDefaultParameterValues['it:skip'] = $true + } + Describe " WSMan SessionOption object" -Tag @("CI") { + It "The SessionOption type exists" { + "Microsoft.WSMan.Management.SessionOption" -as "Type" | Should Not BeNullOrEmpty + } + It "The SessionOption type can be created" { + $result = [Microsoft.WSMan.Management.SessionOption]::new() + $result | should BeOfType "Microsoft.WSMan.Management.SessionOption" + } + It "The SessionOption type has the proper properties when created with the default constructor" { + $result = [Microsoft.WSMan.Management.SessionOption]::new() + $result.SkipCACheck | should be $False + $result.SkipCNCheck | should be $False + $result.SkipRevocationCheck | should be $False + $result.UseEncryption | should be $True + $result.UseUtf16 | should be $False + $result.ProxyAuthentication | should be 0 + $result.SPNPort | should be 0 + $result.OperationTimeout | should be 0 + $result.ProxyCredential | should BeNullOrEmpty + $result.ProxyAccessType | should be ProxyIEConfig + } + It "The values of SessionOption may be set" { + $result = [Microsoft.WSMan.Management.SessionOption]::new() + $result.SkipCACheck = $true + $result.SkipCNCheck = $true + $result.SkipRevocationCheck = $true + $result.UseUtf16 = $True + $result.UseEncryption = $false + $result.ProxyAuthentication = "Negotiate" + $result.SPNPort = 10 + $result.OperationTimeout = 10 + $result.ProxyAccessType = "ProxyAutoDetect" + $result.ProxyCredential = [System.Net.NetworkCredential]::new("user","pass") + + $result.SkipCACheck | should be $true + $result.SkipCNCheck | should be $true + $result.SkipRevocationCheck | should be $true + $result.UseEncryption | should be $False + $result.UseUtf16 | should be $True + $result.ProxyAuthentication | should be "Negotiate" + $result.SPNPort | should be 10 + $result.OperationTimeout | should be 10 + $result.ProxyCredential | should Not BeNullOrEmpty + $result.ProxyAccessType | should be "ProxyAutoDetect" + } + } +} +finally { + $PSDefaultParameterValues.remove("it:skip") +} diff --git a/tools/travis.sh b/tools/travis.sh index 24765d17e5..f3ffb724b2 100755 --- a/tools/travis.sh +++ b/tools/travis.sh @@ -1,7 +1,10 @@ set -x ulimit -n 4096 +# do this for our daily build test run +if [[ "$TRAVIS_EVENT_TYPE" == "cron" ]]; then + powershell -c "Import-Module ./build.psm1; Start-PSBootstrap; Start-PSBuild -CrossGen; Start-PSPester -Tag @('CI','Feature','Scenario') -ExcludeTag RequireAdminOnWindows; Start-PSxUnit" # Only build packages for branches, not pull requests -if [[ "$TRAVIS_PULL_REQUEST" == "false" ]]; then +elif [[ "$TRAVIS_PULL_REQUEST" == "false" ]]; then powershell -c "Import-Module ./build.psm1; Start-PSBootstrap -Package; Start-PSBuild -CrossGen; Start-PSPackage; Start-PSPester -ThrowOnFailure; Test-PSPesterResults; Start-PSxUnit" else powershell -c "Import-Module ./build.psm1; Start-PSBootstrap; Start-PSBuild -CrossGen; Start-PSPester -ThrowOnFailure; Start-PSxUnit"