diff --git a/.travis.yml b/.travis.yml index 472f23a807d..b84708f21af 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,8 @@ addons: artifacts: paths: - $(ls powershell*{deb,pkg,AppImage,gz} | tr "\n" ":") - - pester-tests.xml + - TestResultsSudo.xml + - TestResultsNoSudo.xml install: # Default 2.0.0 Ruby is buggy diff --git a/build.psm1 b/build.psm1 index 2acbd36713e..3cf30f5836b 100644 --- a/build.psm1 +++ b/build.psm1 @@ -898,7 +898,7 @@ function Get-PesterTag { } $values = $vAst.FindAll({$args[0] -is "System.Management.Automation.Language.StringConstantExpressionAst"},$true).Value $values | ForEach-Object { - if (@('REQUIREADMINONWINDOWS', 'SLOW') -contains $_) { + if (@('REQUIREADMINONWINDOWS', 'REQUIRESUDOONUNIX', 'SLOW') -contains $_) { # These are valid tags also, but they are not the priority tags } elseif (@('CI', 'FEATURE', 'SCENARIO') -contains $_) { @@ -980,6 +980,8 @@ function Start-PSPester { [switch]$Terse, [Parameter(ParameterSetName='PassThru',Mandatory=$true)] [switch]$PassThru, + [Parameter(ParameterSetName='PassThru',HelpMessage='Run commands on Linux with sudo.')] + [switch]$Sudo, [switch]$IncludeFailingTest ) @@ -1028,52 +1030,52 @@ Restore the module to '$Pester' by running: Publish-PSTestTools | ForEach-Object {Write-Host $_} # All concatenated commands/arguments are suffixed with the delimiter (space) - $Command = "" + $command = "" if ($Terse) { - $Command += "`$ProgressPreference = 'silentlyContinue'; " + $command += "`$ProgressPreference = 'silentlyContinue'; " } # Autoload (in subprocess) temporary modules used in our tests - $Command += '$env:PSModulePath = '+"'$TestModulePath$TestModulePathSeparator'" + '+$($env:PSModulePath);' + $command += '$env:PSModulePath = '+"'$TestModulePath$TestModulePathSeparator'" + '+$($env:PSModulePath);' # Windows needs the execution policy adjusted if ($Environment.IsWindows) { - $Command += "Set-ExecutionPolicy -Scope Process Unrestricted; " + $command += "Set-ExecutionPolicy -Scope Process Unrestricted; " } - $Command += "Import-Module '$Pester'; " + $command += "Import-Module '$Pester'; " if ($Unelevate) { $outputBufferFilePath = [System.IO.Path]::GetTempFileName() } - $Command += "Invoke-Pester " + $command += "Invoke-Pester " - $Command += "-OutputFormat ${OutputFormat} -OutputFile ${OutputFile} " + $command += "-OutputFormat ${OutputFormat} -OutputFile ${OutputFile} " if ($ExcludeTag -and ($ExcludeTag -ne "")) { - $Command += "-ExcludeTag @('" + (${ExcludeTag} -join "','") + "') " + $command += "-ExcludeTag @('" + (${ExcludeTag} -join "','") + "') " } if ($Tag) { - $Command += "-Tag @('" + (${Tag} -join "','") + "') " + $command += "-Tag @('" + (${Tag} -join "','") + "') " } # sometimes we need to eliminate Pester output, especially when we're # doing a daily build as the log file is too large if ( $Quiet ) { - $Command += "-Quiet " + $command += "-Quiet " } if ( $PassThru ) { - $Command += "-PassThru " + $command += "-PassThru " } - $Command += "'" + ($Path -join "','") + "'" + $command += "'" + ($Path -join "','") + "'" if ($Unelevate) { - $Command += " *> $outputBufferFilePath; '__UNELEVATED_TESTS_THE_END__' >> $outputBufferFilePath" + $command += " *> $outputBufferFilePath; '__UNELEVATED_TESTS_THE_END__' >> $outputBufferFilePath" } - Write-Verbose $Command + Write-Verbose $command $script:nonewline = $true $script:inerror = $false @@ -1162,31 +1164,36 @@ Restore the module to '$Pester' by running: $passThruFile = [System.IO.Path]::GetTempFileName() try { - $Command += "|Export-Clixml -Path '$passThruFile' -Force" - if ($Terse) - { - Start-NativeExecution -sb {& $powershell -noprofile -c $Command} | ForEach-Object { Write-Terse $_} + $command += "|Export-Clixml -Path '$passThruFile' -Force" + + $passThruCommand = {& $powershell -noprofile -c $command } + if ($Sudo.IsPresent) { + $passThruCommand = {& sudo $powershell -noprofile -c $command } } - else + + $writeCommand = { Write-Host $_ } + if ($Terse) { - Start-NativeExecution -sb {& $powershell -noprofile -c $Command} | ForEach-Object { Write-Host $_} + $writeCommand = { Write-Terse $_ } } + + Start-NativeExecution -sb $passThruCommand | ForEach-Object $writeCommand Import-Clixml -Path $passThruFile | Where-Object {$_.TotalCount -is [Int32]} } finally { - Remove-Item $passThruFile -ErrorAction SilentlyContinue + Remove-Item $passThruFile -ErrorAction SilentlyContinue -Force } } else { if ($Terse) { - Start-NativeExecution -sb {& $powershell -noprofile -c $Command} | ForEach-Object { Write-Terse -line $_ } + Start-NativeExecution -sb {& $powershell -noprofile -c $command} | ForEach-Object { Write-Terse -line $_ } } else { - Start-NativeExecution -sb {& $powershell -noprofile -c $Command} + Start-NativeExecution -sb {& $powershell -noprofile -c $command} } } } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Set-Date.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Set-Date.Tests.ps1 index e3de326fea1..387bea1bfc8 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Set-Date.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Set-Date.Tests.ps1 @@ -1,14 +1,11 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. -Describe "Set-Date for admin" -Tag @('CI', 'RequireAdminOnWindows') { - # Currently, CI tests on Linux/macOS are always run as normal user. So we need to skip these tests on non-Windows platform. - # CI tests in root privilege on Linux/macOS is not supported. - # See : https://github.com/PowerShell/PowerShell/issues/5645 - It "Set-Date should be able to set the date in an elevated context" -Skip:(!$IsWindows) { +Describe "Set-Date for admin" -Tag @('CI', 'RequireAdminOnWindows', 'RequireSudoOnUnix') { + It "Set-Date should be able to set the date in an elevated context" { { Get-Date | Set-Date } | Should Not Throw } - It "Set-Date should be able to set the date with -Date parameter" -Skip:(!$IsWindows) { + It "Set-Date should be able to set the date with -Date parameter" { $target = Get-Date $expected = $target Set-Date -Date $target | Should Be $expected diff --git a/tools/travis.ps1 b/tools/travis.ps1 index 9005dbdc4db..d5bbdf52509 100644 --- a/tools/travis.ps1 +++ b/tools/travis.ps1 @@ -200,10 +200,16 @@ elseif($Stage -eq 'Build') $ProgressPreference = $originalProgressPreference } + $testResultsNoSudo = "$pwd/TestResultsNoSudo.xml" + $testResultsSudo = "$pwd/TestResultsSudo.xml" + $pesterParam = @{ - 'binDir' = $output - 'PassThru' = $true - 'Terse' = $true + 'binDir' = $output + 'PassThru' = $true + 'Terse' = $true + 'Tag' = @() + 'ExcludeTag' = @('RequireSudoOnUnix') + 'OutputFile' = $testResultsNoSudo } if ($isFullBuild) { @@ -225,12 +231,20 @@ elseif($Stage -eq 'Build') Remove-Item -force ${telemetrySemaphoreFilepath} } - $pesterPassThruObject = Start-PSPester @pesterParam + # Running tests which do not require sudo. + $pesterPassThruNoSudoObject = Start-PSPester @pesterParam + + # Running tests, which require sudo. + $pesterParam['Tag'] = @('RequireSudoOnUnix') + $pesterParam['ExcludeTag'] = @() + $pesterParam['Sudo'] = $true + $pesterParam['OutputFile'] = $testResultsSudo + $pesterPassThruSudoObject = Start-PSPester @pesterParam # Determine whether the build passed try { # this throws if there was an error - Test-PSPesterResults -ResultObject $pesterPassThruObject + @($pesterPassThruNoSudoObject, $pesterPassThruSudoObject) | ForEach-Object { Test-PSPesterResults -ResultObject $_ } $result = "PASS" } catch {