From dd0291be09c91083ef04f9443b7319bf345f16d3 Mon Sep 17 00:00:00 2001 From: James Truher Date: Mon, 25 Jul 2016 11:06:55 -0700 Subject: [PATCH] update encoding on the test files - these are ascii --- .../Pester.Commands.Cmdlets.Archive.Tests.ps1 | 1938 +++++------ .../History.Tests.ps1 | 128 +- ...ster.Commands.Cmdlets.GetCommand.Tests.ps1 | 104 +- .../Copy.Item.Tests.ps1 | 1736 +++++----- ...mands.Cmdlets.NoNewlineParameter.Tests.ps1 | 52 +- .../FormatHex.Tests.ps1 | 442 +-- .../ImportExportCSV.Delimiter.Tests.ps1 | 168 +- .../MiscCmdletUpdates.Tests.ps1 | 108 +- .../NewGuid.Tests.ps1 | 38 +- .../NewTemporaryFile.Tests.ps1 | 76 +- .../Pester.Commands.Cmdlets.Json.Tests.ps1 | 2891 ++++++++--------- .../PowerShellData.tests.ps1 | 172 +- .../alias.tests.ps1 | 320 +- .../clixml.tests.ps1 | 374 +-- .../command.tests.ps1 | 160 +- .../formatdata.tests.ps1 | 128 +- .../object.tests.ps1 | 200 +- .../string.tests.ps1 | 126 +- .../typedata.tests.ps1 | Bin 10592 -> 5169 bytes .../xml.tests.ps1 | 136 +- 20 files changed, 4628 insertions(+), 4669 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Archive/Pester.Commands.Cmdlets.Archive.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Archive/Pester.Commands.Cmdlets.Archive.Tests.ps1 index 3c1d055f2a..f8ac581f8e 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Archive/Pester.Commands.Cmdlets.Archive.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Archive/Pester.Commands.Cmdlets.Archive.Tests.ps1 @@ -1,969 +1,969 @@ -<############################################################################################ - # File: Pester.Commands.Cmdlets.ArchiveTests.ps1 - # Commands.Cmdlets.ArchiveTests suite contains Tests that are - # used for validating Microsoft.PowerShell.Archive module. - ############################################################################################> -$script:TestSourceRoot = $PSScriptRoot -Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "CI" { - - AfterAll { - $global:ProgressPreference = $_progressPreference - } - BeforeAll { - # Write-Progress not supported yet on Core - $_progressPreference = $ProgressPreference - if ( $IsCore ) { $global:ProgressPreference = "SilentlyContinue" } - - Setup -d SourceDir - Setup -d SourceDir/ChildDir-1 - Setup -d SourceDir/ChildDir-2 - Setup -d SourceDir/ChildEmptyDir - - $content = "Some Data" - $Files = ( [io.path]::Combine("SourceDir","Sample-1.txt")), ([io.path]::Combine("SourceDir","Sample-2.txt")), - ([io.path]::Combine("SourceDir","ChildDir-1","Sample-3.txt")), ([io.path]::Combine("SourceDir","ChildDir-1","Sample-4.txt")), - ([io.path]::Combine("SourceDir","ChildDir-2","Sample-5.txt")), ([io.path]::Combine("SourceDir","ChildDir-2","Sample-6.txt")) - - foreach($file in $files ) { - Setup -f $file -content $content - } - - Setup -f Sample.unzip -content "Some Text" - Setup -f Sample.cab -content "Some Text" - - $preCreatedArchivePath = Join-Path $script:TestSourceRoot "SamplePreCreatedArchive.archive" - Copy-Item $preCreatedArchivePath $TestDrive/SamplePreCreatedArchive.zip -Force - } - - function Add-CompressionAssemblies { - Add-Type -AssemblyName System.IO.Compression - if (($psedition -eq "Core") -or $IsCore ) - { - Add-Type -AssemblyName System.IO.Compression.ZipFile - } - else - { - Add-Type -AssemblyName System.IO.Compression.FileSystem - } - } - - function CompressArchivePathParameterSetValidator { - param - ( - [string[]] $path, - [string] $destinationPath, - [string] $compressionLevel = "Optimal" - ) - - try - { - Compress-Archive -Path $path -DestinationPath $destinationPath -CompressionLevel $compressionLevel - trow "ValidateNotNullOrEmpty attribute is missing on one of parameters belonging to Path parameterset." - } - catch - { - $_.FullyQualifiedErrorId | Should Be "ParameterArgumentValidationError,Compress-Archive" - } - } - - function CompressArchiveLiteralPathParameterSetValidator { - param - ( - [string[]] $literalPath, - [string] $destinationPath, - [string] $compressionLevel = "Optimal" - ) - - try - { - Compress-Archive -LiteralPath $literalPath -DestinationPath $destinationPath -CompressionLevel $compressionLevel - throw "ValidateNotNullOrEmpty attribute is missing on one of parameters belonging to LiteralPath parameterset." - } - catch - { - $_.FullyQualifiedErrorId | Should Be "ParameterArgumentValidationError,Compress-Archive" - } - } - - - function CompressArchiveInValidPathValidator { - param - ( - [string[]] $path, - [string] $destinationPath, - [string] $invalidPath, - [string] $expectedFullyQualifiedErrorId - ) - - try - { - Compress-Archive -Path $path -DestinationPath $destinationPath - throw "Failed to validate that an invalid Path $invalidPath was supplied as input to Compress-Archive cmdlet." - } - catch - { - $_.FullyQualifiedErrorId | Should Be $expectedFullyQualifiedErrorId - } - } - - function CompressArchiveInValidArchiveFileExtensionValidator { - param - ( - [string[]] $path, - [string] $destinationPath, - [string] $invalidArchiveFileExtension - ) - - try - { - Compress-Archive -Path $path -DestinationPath $destinationPath - throw "Failed to validate that an invalid archive file format $invalidArchiveFileExtension was supplied as input to Compress-Archive cmdlet." - } - catch - { - $_.FullyQualifiedErrorId | Should Be "NotSupportedArchiveFileExtension,Compress-Archive" - } - } - - function Validate-ArchiveEntryCount { - param - ( - [string] $path, - [int] $expectedEntryCount - ) - - Add-CompressionAssemblies - try - { - $archiveFileStreamArgs = @($path, [System.IO.FileMode]::Open) - $archiveFileStream = New-Object -TypeName System.IO.FileStream -ArgumentList $archiveFileStreamArgs - - $zipArchiveArgs = @($archiveFileStream, [System.IO.Compression.ZipArchiveMode]::Read, $false) - $zipArchive = New-Object -TypeName System.IO.Compression.ZipArchive -ArgumentList $zipArchiveArgs - - $actualEntryCount = $zipArchive.Entries.Count - $actualEntryCount | Should Be $expectedEntryCount - } - finally - { - if ($null -ne $zipArchive) { $zipArchive.Dispose()} - if ($null -ne $archiveFileStream) { $archiveFileStream.Dispose() } - } - } - - function ArchiveFileEntryContentValidator { - param - ( - [string] $path, - [string] $entryFileName, - [string] $expectedEntryFileContent - ) - - Add-CompressionAssemblies - try - { - $destFile = "$TestDrive/ExpandedFile"+([System.Guid]::NewGuid().ToString())+".txt" - - $archiveFileStreamArgs = @($path, [System.IO.FileMode]::Open) - $archiveFileStream = New-Object -TypeName System.IO.FileStream -ArgumentList $archiveFileStreamArgs - - $zipArchiveArgs = @($archiveFileStream, [System.IO.Compression.ZipArchiveMode]::Read, $false) - $zipArchive = New-Object -TypeName System.IO.Compression.ZipArchive -ArgumentList $zipArchiveArgs - - $entryToBeUpdated = $zipArchive.Entries | ? {$_.FullName -eq $entryFileName} - - if($entryToBeUpdated -ne $null) - { - $srcStream = $entryToBeUpdated.Open() - $destStream = New-Object "System.IO.FileStream" -ArgumentList( $destFile, [System.IO.FileMode]::Create ) - $srcStream.CopyTo( $destStream ) - $destStream.Dispose() - $srcStream.Dispose() - Get-Content $destFile | Should Be $expectedEntryFileContent - } - else - { - throw "Failed to find the file $entryFileName in the archive file $path" - } - } - finally - { - if ($zipArchive) - { - $zipArchive.Dispose() - } - if ($archiveFileStream) - { - $archiveFileStream.Dispose() - } - } - } - - function ExpandArchiveInvalidParameterValidator { - param - ( - [boolean] $isLiteralPathParameterSet, - [string[]] $path, - [string] $destinationPath, - [string] $expectedFullyQualifiedErrorId - ) - - try - { - if($isLiteralPathParameterSet) - { - Expand-Archive -LiteralPath $literalPath -DestinationPath $destinationPath - } - else - { - Expand-Archive -Path $path -DestinationPath $destinationPath - } - - throw "Expand-Archive did NOT throw expected error" - } - catch - { - $_.FullyQualifiedErrorId | Should Be $expectedFullyQualifiedErrorId - } - } - - Context "Compress-Archive - Parameter validation test cases" { - - It "Validate errors from Compress-Archive with NULL & EMPTY values for Path, LiteralPath, DestinationPath, CompressionLevel parameters" { - $sourcePath = "$TestDrive/SourceDir" - $destinationPath = "$TestDrive/SampleSingleFile.zip" - - CompressArchivePathParameterSetValidator $null $destinationPath - CompressArchivePathParameterSetValidator $sourcePath $null - CompressArchivePathParameterSetValidator $null $null - - CompressArchivePathParameterSetValidator "" $destinationPath - CompressArchivePathParameterSetValidator $sourcePath "" - CompressArchivePathParameterSetValidator "" "" - - CompressArchivePathParameterSetValidator $null $null "NoCompression" - - CompressArchiveLiteralPathParameterSetValidator $null $destinationPath - CompressArchiveLiteralPathParameterSetValidator $sourcePath $null - CompressArchiveLiteralPathParameterSetValidator $null $null - - CompressArchiveLiteralPathParameterSetValidator "" $destinationPath - CompressArchiveLiteralPathParameterSetValidator $sourcePath "" - CompressArchiveLiteralPathParameterSetValidator "" "" - - CompressArchiveLiteralPathParameterSetValidator $null $null "NoCompression" - - CompressArchiveLiteralPathParameterSetValidator $sourcePath $destinationPath $null - CompressArchiveLiteralPathParameterSetValidator $sourcePath $destinationPath "" - } - - It "Validate errors from Compress-Archive when invalid path (non-existing path / non-filesystem path) is supplied for Path or LiteralPath parameters" { - CompressArchiveInValidPathValidator "$TestDrive/InvalidPath" $TestDrive "$TestDrive/InvalidPath" "ArchiveCmdletPathNotFound,Compress-Archive" - if ( ! $IsCore ) { - CompressArchiveInValidPathValidator "HKLM:/SOFTWARE" $TestDrive "HKLM:/SOFTWARE" "PathNotFound,Compress-Archive" - } - CompressArchiveInValidPathValidator "$TestDrive" "$TestDrive/NonExistingDirectory/sample.zip" "$TestDrive/NonExistingDirectory/sample.zip" "ArchiveCmdletPathNotFound,Compress-Archive" - - $path = @("$TestDrive", "$TestDrive/InvalidPath") - CompressArchiveInValidPathValidator $path $TestDrive "$TestDrive/InvalidPath" "ArchiveCmdletPathNotFound,Compress-Archive" - - if ( ! $IsCore ) { - $path = @("$TestDrive", "HKLM:/SOFTWARE") - CompressArchiveInValidPathValidator $path $TestDrive "HKLM:/SOFTWARE" "PathNotFound,Compress-Archive" - } - - $invalidUnZipFileFormat = "$TestDrive/Sample.unzip" - CompressArchiveInValidArchiveFileExtensionValidator $TestDrive "$invalidUnZipFileFormat" ".unzip" - - $invalidcabZipFileFormat = "$TestDrive/Sample.cab" - CompressArchiveInValidArchiveFileExtensionValidator $TestDrive "$invalidcabZipFileFormat" ".cab" - } - - It "Validate error from Compress-Archive when archive file already exists and -Update parameter is not specified" { - $sourcePath = "$TestDrive/SourceDir" - $destinationPath = "$TestDrive/ValidateErrorWhenUpdateNotSpecified.zip" - - try - { - "Some Data" > $destinationPath - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - throw "Failed to validate that an archive file format $destinationPath already exists and -Update switch parameter is not specified while running Compress-Archive command." - } - catch - { - $_.FullyQualifiedErrorId | Should Be "ArchiveFileExists,Compress-Archive" - } - } - - It "Validate error from Compress-Archive when duplicate paths are supplied as input to Path parameter" { - $sourcePath = @( - "$TestDrive/SourceDir/Sample-1.txt", - "$TestDrive/SourceDir/Sample-1.txt") - $destinationPath = "$TestDrive/DuplicatePaths.zip" - - try - { - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - throw "Failed to detect that duplicate Path $sourcePath is supplied as input to Path parameter." - } - catch - { - $_.FullyQualifiedErrorId | Should Be "DuplicatePathFound,Compress-Archive" - } - } - - It "Validate error from Compress-Archive when duplicate paths are supplied as input to LiteralPath parameter" { - $sourcePath = @( - "$TestDrive/SourceDir/Sample-1.txt", - "$TestDrive/SourceDir/Sample-1.txt") - $destinationPath = "$TestDrive/DuplicatePaths.zip" - - try - { - Compress-Archive -LiteralPath $sourcePath -DestinationPath $destinationPath - throw "Failed to detect that duplicate Path $sourcePath is supplied as input to LiteralPath parameter." - } - catch - { - $_.FullyQualifiedErrorId | Should Be "DuplicatePathFound,Compress-Archive" - } - } - - It "Validate that relative path can be specified as Path parameter of Compress-Archive cmdlet" { - $sourcePath = "./SourceDir" - $destinationPath = "RelativePathForPathParameter.zip" - try { - push-location $TESTDRIVE - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - Test-Path $destinationPath | Should Be $true - } - finally { - Pop-Location - } - } - It "Validate that relative path can be specified as LiteralPath parameter of Compress-Archive cmdlet" { - $sourcePath = "./SourceDir" - $destinationPath = "RelativePathForLiteralPathParameter.zip" - try { - push-location $TESTDRIVE - Compress-Archive -LiteralPath $sourcePath -DestinationPath $destinationPath - Test-Path $destinationPath | Should Be $true - } - finally { - Pop-Location - } - } - It "Validate that relative path can be specified as DestinationPath parameter of Compress-Archive cmdlet" { - $sourcePath = "$TestDrive/SourceDir" - $destinationPath = "./RelativePathForDestinationPathParameter.zip" - try { - push-location $TESTDRIVE - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - Test-Path $destinationPath | Should Be $true - } - finally { - Pop-Location - } - } - } - - Context "Compress-Archive - functional test cases" { - It "Validate that a single file can be compressed using Compress-Archive cmdlet" { - $sourcePath = [io.path]::Combine("$TestDrive","SourceDir","ChildDir-1","Sample-3.txt") - $destinationPath = [io.path]::Combine("$TestDrive","SampleSingleFile.zip") - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - $destinationPath | Should Exist - } - # This test requires a fix in PS5 to support reading paths with square bracket - It "Validate that Compress-Archive cmdlet can accept LiteralPath parameter with Special Characters" -skip:($PSVersionTable.psversion -lt "5.0") { - $sourcePath = "$TestDrive/SourceDir/ChildDir-1/Sample[]File.txt" - "Some Random Content" | Out-File -LiteralPath $sourcePath - $destinationPath = "$TestDrive/SampleSingleFileWithSpecialCharacters.zip" - try - { - Compress-Archive -LiteralPath $sourcePath -DestinationPath $destinationPath - $destinationPath | Should Exist - } - finally - { - get-item -literalPath $sourcePath | remove-Item -force - # Remove-Item -LiteralPath $sourcePath -Force - } - } - It "Validate that Compress-Archive cmdlet errors out when DestinationPath resolves to multiple locations" { - - New-Item $TestDrive/SampleDir/Child-1 -Type Directory -Force | Out-Null - New-Item $TestDrive/SampleDir/Child-2 -Type Directory -Force | Out-Null - New-Item $TestDrive/SampleDir/Test.txt -Type File -Force | Out-Null - - $destinationPath = "$TestDrive/SampleDir/Child-*/SampleChidArchive.zip" - $sourcePath = "$TestDrive/SampleDir/Test.txt" - try - { - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - throw "Failed to detect that destination $destinationPath can resolve to multiple paths" - } - catch - { - $_.FullyQualifiedErrorId | Should Be "InvalidArchiveFilePath,Compress-Archive" - } - finally - { - Remove-Item -LiteralPath $TestDrive/SampleDir -Force -Recurse - } - } - It "Validate that Compress-Archive cmdlet works when DestinationPath has wild card pattern and resolves to a single valid path" { - - New-Item $TestDrive/SampleDir/Child-1 -Type Directory -Force | Out-Null - New-Item $TestDrive/SampleDir/Test.txt -Type File -Force | Out-Null - - $destinationPath = "$TestDrive/SampleDir/Child-*/SampleChidArchive.zip" - $sourcePath = "$TestDrive/SampleDir/Test.txt" - try - { - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - $destinationPath | Should Exist - } - finally - { - Remove-Item -LiteralPath $TestDrive/SampleDir -Force -Recurse - } - } - # This test requires a fix in PS5 to support reading paths with square bracket - It "Validate that Compress-Archive cmdlet can accept LiteralPath parameter for a directory with Special Characters in the directory name" -skip:($PSVersionTable.psversion -lt "5.0") { - $sourcePath = "$TestDrive/Source[]Dir/ChildDir[]-1" - New-Item $sourcePath -Type Directory | Out-Null - "Some Random Content" | Out-File -LiteralPath "$sourcePath/Sample[]File.txt" - $destinationPath = "$TestDrive/SampleDirWithSpecialCharacters.zip" - try - { - Compress-Archive -LiteralPath $sourcePath -DestinationPath $destinationPath - $destinationPath | Should Exist - } - finally - { - get-item -LiteralPath $sourcePath | Remove-Item -Force -Recurse - # Remove-Item -LiteralPath $sourcePath -Force -Recurse - } - } - It "Validate that Compress-Archive cmdlet can accept DestinationPath parameter with Special Characters" { - $sourcePath = "$TestDrive/SourceDir/ChildDir-1/Sample-3.txt" - $destinationPath = "$TestDrive/Sample[]SingleFile.zip" - try - { - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - Test-Path -LiteralPath $destinationPath | Should Be $true - } - finally - { - Get-Item -LiteralPath $destinationPath | Remove-Item -Force - # Remove-Item -LiteralPath $destinationPath -Force - } - } - It "Validate that Source Path can be at SystemDrive location" -skip:($IsCore) { - $sourcePath = "$env:SystemDrive/SourceDir" - $destinationPath = "$TestDrive/SampleFromSystemDrive.zip" - New-Item $sourcePath -Type Directory | Out-Null - "Some Data" | Out-File -FilePath $sourcePath/SampleSourceFileForArchive.txt - try - { - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - Test-Path $destinationPath | Should Be $true - } - finally - { - remove-item "$sourcePath" -Force -Recurse -ErrorAction SilentlyContinue - } - } - It "Validate that multiple files can be compressed using Compress-Archive cmdlet" { - $sourcePath = @( - "$TestDrive/SourceDir/ChildDir-1/Sample-3.txt", - "$TestDrive/SourceDir/ChildDir-1/Sample-4.txt", - "$TestDrive/SourceDir/ChildDir-2/Sample-5.txt", - "$TestDrive/SourceDir/ChildDir-2/Sample-6.txt") - $destinationPath = "$TestDrive/SampleMultipleFiles.zip" - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - Test-Path $destinationPath | Should Be $true - } - It "Validate that multiple files and directories can be compressed using Compress-Archive cmdlet" { - $sourcePath = @( - "$TestDrive/SourceDir/Sample-1.txt", - "$TestDrive/SourceDir/Sample-2.txt", - "$TestDrive/SourceDir/ChildDir-1", - "$TestDrive/SourceDir/ChildDir-2") - $destinationPath = "$TestDrive/SampleMultipleFilesAndDirs.zip" - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - Test-Path $destinationPath | Should Be $true - } - It "Validate that a single directory can be compressed using Compress-Archive cmdlet" { - $sourcePath = @("$TestDrive/SourceDir/ChildDir-1") - $destinationPath = "$TestDrive/SampleSingleDir.zip" - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - Test-Path $destinationPath | Should Be $true - } - It "Validate that a single directory with multiple files and subdirectories can be compressed using Compress-Archive cmdlet" { - $sourcePath = @("$TestDrive/SourceDir") - $destinationPath = "$TestDrive/SampleSubTree.zip" - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - Test-Path $destinationPath | Should Be $true - } - It "Validate that a single directory & multiple files can be compressed using Compress-Archive cmdlet" { - $sourcePath = @( - "$TestDrive/SourceDir/ChildDir-1", - "$TestDrive/SourceDir/Sample-1.txt", - "$TestDrive/SourceDir/Sample-2.txt") - $destinationPath = "$TestDrive/SampleMultipleFilesAndSingleDir.zip" - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - Test-Path $destinationPath | Should Be $true - } - - It "Validate that if .zip extension is not supplied as input to DestinationPath parameter, then .zip extension is appended" { - $sourcePath = @("$TestDrive/SourceDir") - $destinationPath = "$TestDrive/SampleNoExtension.zip" - $destinationWithoutExtensionPath = "$TestDrive/SampleNoExtension" - Compress-Archive -Path $sourcePath -DestinationPath $destinationWithoutExtensionPath - Test-Path $destinationPath | Should Be $true - } - - It "Validate that -Update parameter makes Compress-Archive to not throw an error if archive file already exists" { - $sourcePath = @("$TestDrive/SourceDir") - $destinationPath = "$TestDrive/SampleUpdateTest.zip" - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - Test-Path $destinationPath | Should Be $true - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -Update - Test-Path $destinationPath | Should Be $true - } - It "Validate -Update parameter by adding a new file to an existing archive file" { - $sourcePath = @("$TestDrive/SourceDir/ChildDir-1") - $destinationPath = "$TestDrive/SampleUpdateAdd1File.zip" - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - Test-Path $destinationPath | Should Be $true - New-Item $TestDrive/SourceDir/ChildDir-1/Sample-AddedNewFile.txt -Type File | Out-Null - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -Update - Test-Path $destinationPath | Should Be $true - Validate-ArchiveEntryCount -path $destinationPath -expectedEntryCount 3 - } - - It "Validate that all CompressionLevel values can be used with Compress-Archive cmdlet" { - $sourcePath = "$TestDrive/SourceDir/Sample-1.txt" - - $destinationPath = "$TestDrive/FastestCompressionLevel.zip" - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -CompressionLevel Fastest - Test-Path $destinationPath | Should Be $true - - $destinationPath = "$TestDrive/OptimalCompressionLevel.zip" - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -CompressionLevel Optimal - Test-Path $destinationPath | Should Be $true - - $destinationPath = "$TestDrive/NoCompressionCompressionLevel.zip" - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -CompressionLevel NoCompression - Test-Path $destinationPath | Should Be $true - } - - It "Validate that -Update parameter is modifying a file that already exists in the archive file" { - $filePath = "$TestDrive/SourceDir/ChildDir-1/Sample-3.txt" - - $initialContent = "Initial Content" - $modifiedContent = "Modified Content" - - $initialContent | Set-Content $filePath - - $sourcePath = "$TestDrive/SourceDir" - $destinationPath = "$TestDrive/UpdatingModifiedFile.zip" - - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - Test-Path $destinationPath | Should Be $True - - $modifiedContent | Set-Content $filePath - - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -Update - Test-Path $destinationPath | Should Be $True - - ArchiveFileEntryContentValidator "$destinationPath" ([io.path]::Combine("SourceDir","ChildDir-1","Sample-3.txt")) $modifiedContent - } - - It "Validate Compress-Archive cmdlet in pipleline scenario" { - $destinationPath = "$TestDrive/CompressArchiveFromPipeline.zip" - - # Piping a single file path to Compress-Archive - dir -Path $TestDrive/SourceDir/Sample-1.txt | Compress-Archive -DestinationPath $destinationPath - Test-Path $destinationPath | Should Be $True - - # Piping a string directory path to Compress-Archive - "$TestDrive/SourceDir/ChildDir-2" | Compress-Archive -DestinationPath $destinationPath -Update - Test-Path $destinationPath | Should Be $True - - # Piping the output of Get-ChildItem to Compress-Archive - dir "$TestDrive/SourceDir" -Recurse | Compress-Archive -DestinationPath $destinationPath -Update - Test-Path $destinationPath | Should Be $True - } - - It "Validate that Compress-Archive works on ReadOnly files" { - $sourcePath = "$TestDrive/ReadOnlyFile.txt" - $destinationPath = "$TestDrive/TestForReadOnlyFile.zip" - - "Some Content" | Out-File -FilePath $sourcePath - $createdItem = Get-Item $sourcePath - $createdItem.Attributes = 'ReadOnly' - - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - Test-Path $destinationPath | Should Be $true - } - - It "Validate that Compress-Archive generates Verbose messages" { - $sourcePath = "$TestDrive/SourceDir" - $destinationPath = "$TestDrive/Compress-Archive generates VerboseMessages.zip" - - try - { - $ps=[PowerShell]::Create() - $ps.Streams.Error.Clear() - $ps.Streams.Verbose.Clear() - $script = "Import-Module Microsoft.PowerShell.Archive; Compress-Archive -Path $sourcePath -DestinationPath `"$destinationPath`" -CompressionLevel Fastest -Verbose" - $ps.AddScript($script) - $ps.Invoke() - - $ps.Streams.Verbose.Count -gt 0 | Should Be $True - $ps.Streams.Error.Count | Should Be 0 - } - finally - { - $ps.Dispose() - } - } - } - - Context "Expand-Archive - Parameter validation test cases" { - It "Validate non existing archive -Path trows expected error message" { - $sourcePath = "$TestDrive/SourceDir" - $destinationPath = "$TestDrive/ExpandedArchive" - try - { - Expand-Archive -Path $sourcePath -DestinationPath $destinationPath - throw "Expand-Archive succeeded for non existing archive path" - } - catch - { - $_.FullyQualifiedErrorId | Should Be "PathNotFound,Expand-Archive" - } - } - - It "Validate errors from Expand-Archive with NULL & EMPTY values for Path, LiteralPath, DestinationPath parameters" { - ExpandArchiveInvalidParameterValidator $false $null "$TestDrive/SourceDir" "ParameterArgumentValidationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $false $null $null "ParameterArgumentValidationError,Expand-Archive" - - ExpandArchiveInvalidParameterValidator $false "$TestDrive/SourceDir" $null "ParameterArgumentTransformationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $false "" "$TestDrive/SourceDir" "ParameterArgumentTransformationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $false "$TestDrive/SourceDir" "" "ParameterArgumentTransformationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $false "" "" "ParameterArgumentTransformationError,Expand-Archive" - - ExpandArchiveInvalidParameterValidator $true $null "$TestDrive/SourceDir" "ParameterArgumentValidationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $true $null $null "ParameterArgumentValidationError,Expand-Archive" - - ExpandArchiveInvalidParameterValidator $true "$TestDrive/SourceDir" $null "ParameterArgumentValidationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $true "" "$TestDrive/SourceDir" "ParameterArgumentValidationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $true "$TestDrive/SourceDir" "" "ParameterArgumentValidationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $true "" "" "ParameterArgumentValidationError,Expand-Archive" - - ExpandArchiveInvalidParameterValidator $true $null "$TestDrive/SourceDir" "ParameterArgumentValidationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $true $null $null "ParameterArgumentValidationError,Expand-Archive" - - ExpandArchiveInvalidParameterValidator $true "$TestDrive/SourceDir" $null "ParameterArgumentValidationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $true "" "$TestDrive/SourceDir" "ParameterArgumentValidationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $true "$TestDrive/SourceDir" "" "ParameterArgumentValidationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $true "" "" "ParameterArgumentValidationError,Expand-Archive" - } - - It "Validate errors from Expand-Archive when invalid path (non-existing path / non-filesystem path) is supplied for Path or LiteralPath parameters" { - try { Expand-Archive -Path "$TestDrive/NonExistingArchive" -DestinationPath "$TestDrive/SourceDir"; throw "Expand-Archive did NOT throw expected error" } - catch { $_.FullyQualifiedErrorId | Should Be "ArchiveCmdletPathNotFound,Expand-Archive" } - - if ( ! $IsCore ) { - try { Expand-Archive -Path "HKLM:/SOFTWARE" -DestinationPath "$TestDrive/SourceDir"; throw "Expand-Archive did NOT throw expected error" } - catch { $_.FullyQualifiedErrorId | Should Be "PathNotFound,Expand-Archive" } - } - - try { Expand-Archive -LiteralPath "$TestDrive/NonExistingArchive" -DestinationPath "$TestDrive/SourceDir"; throw "Expand-Archive did NOT throw expected error" } - catch { $_.FullyQualifiedErrorId | Should Be "ArchiveCmdletPathNotFound,Expand-Archive" } - - if ( ! $IsCore ) { - try { Expand-Archive -LiteralPath "HKLM:/SOFTWARE" -DestinationPath "$TestDrive/SourceDir"; throw "Expand-Archive did NOT throw expected error" } - catch { $_.FullyQualifiedErrorId | Should Be "PathNotFound,Expand-Archive" } - } - } - - It "Validate error from Expand-Archive when invalid path (non-existing path / non-filesystem path) is supplied for DestinationPath parameter" { - $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" - # $destinationPath = "HKLM:/SOFTWARE" - $destinationPath = "Variable:/" - - try { Expand-Archive -Path $sourcePath -DestinationPath $destinationPath; throw "Expand-Archive did NOT throw expected error" } - catch { $_.FullyQualifiedErrorId | Should Be "InvalidDirectoryPath,Expand-Archive" } - } - } - - Context "Expand-Archive - functional test cases" { - It "Validate basic Expand-Archive scenario" { - $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" - $content = "Some Data" - $destinationPath = "$TestDrive/DestDirForBasicExpand" - $files = @("Sample-1.txt", "Sample-2.txt") - - # The files in "$TestDrive/SamplePreCreatedArchive.zip" are precreated. - $fileCreationTimeStamp = Get-Date -Year 2014 -Month 6 -Day 13 -Hour 15 -Minute 50 -Second 20 -Millisecond 0 - - Expand-Archive -Path $sourcePath -DestinationPath $destinationPath - foreach($currentFile in $files) - { - $expandedFile = Join-Path $destinationPath -ChildPath $currentFile - Test-Path $expandedFile | Should Be $True - - # We are validating to make sure that time stamps are preserved in the - # compressed archive are reflected back when the file is expanded. - (dir $expandedFile).LastWriteTime.CompareTo($fileCreationTimeStamp) | Should Be 0 - - Get-Content $expandedFile | Should Be $content - } - } - It "Validate that Expand-Archive cmdlet errors out when DestinationPath resolves to multiple locations" { - $testbasename = "TargetDir" - setup -d "$testbasename" - setup -d "$testbasename/Child-1" - setup -d "$testbasename/Child-2" - - $destinationPath = [io.path]::Combine("$TestDrive","$testbasename","Child-*") - $sourcePath = join-path "$TestDrive" "SamplePreCreatedArchive.zip" - try - { - Expand-Archive -Path $sourcePath -DestinationPath $destinationPath - throw "Failed to detect that destination $destinationPath can resolve to multiple paths" - } - catch - { - $_.FullyQualifiedErrorId | Should Be "InvalidDestinationPath,Expand-Archive" - } - finally - { - Remove-Item -LiteralPath "$TestDrive/$testbasename" -Force -Recurse - } - } - It "Validate that Expand-Archive cmdlet works when DestinationPath resolves has wild card pattern and resolves to a single valid path" { - $testbasename = "TargetDir" - setup -d "$testbasename" - setup -d "$testbasename/Child-1" - - $destinationPath = [io.path]::Combine("$TestDrive","$testbasename","Child-*") - $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" - try - { - Expand-Archive -Path $sourcePath -DestinationPath $destinationPath - $expandedFiles = Get-ChildItem $destinationPath -Recurse - $expandedFiles.Length | Should BeGreaterThan 1 - } - finally - { - Remove-Item -LiteralPath "$TestDrive/$testbasename" -Force -Recurse - } - } - It "Validate Expand-Archive scenario where DestinationPath has Special Characters" { - $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" - $content = "Some Data" - $destinationPath = "$TestDrive/DestDir[]Expand" - $files = @("Sample-1.txt", "Sample-2.txt") - - # The files in "$TestDrive/SamplePreCreatedArchive.zip" are precreated. - $fileCreationTimeStamp = Get-Date -Year 2014 -Month 6 -Day 13 -Hour 15 -Minute 50 -Second 20 -Millisecond 0 - - Expand-Archive -Path $sourcePath -DestinationPath $destinationPath - foreach($currentFile in $files) - { - $expandedFile = Join-Path $destinationPath -ChildPath $currentFile - Test-Path -LiteralPath $expandedFile | Should Be $True - - # We are validating to make sure that time stamps are preserved in the - # compressed archive are reflected back when the file is expanded. - (dir -LiteralPath $expandedFile).LastWriteTime.CompareTo($fileCreationTimeStamp) | Should Be 0 - - Get-Content -LiteralPath $expandedFile | Should Be $content - } - } - It "Invoke Expand-Archive with relative path in Path parameter and -Force parameter" { - $sourcePath = "./SamplePreCreatedArchive.zip" - $destinationPath = "$TestDrive/SomeOtherNonExistingDir/Path" - try - { - Push-Location $TestDrive - - Expand-Archive -Path $sourcePath -DestinationPath $destinationPath -Force - $expandedFiles = Get-ChildItem $destinationPath -Recurse - $expandedFiles.Length | Should Be 2 - } - finally - { - Pop-Location - } - } - - It "Invoke Expand-Archive with relative path in LiteralPath parameter and -Force parameter" { - $sourcePath = "./SamplePreCreatedArchive.zip" - $destinationPath = "$TestDrive/SomeOtherNonExistingDir/LiteralPath" - try - { - Push-Location $TestDrive - - Expand-Archive -LiteralPath $sourcePath -DestinationPath $destinationPath -Force - $expandedFiles = Get-ChildItem $destinationPath -Recurse - $expandedFiles.Length | Should Be 2 - } - finally - { - Pop-Location - } - } - - It "Invoke Expand-Archive with non-existing relative directory in DestinationPath parameter and -Force parameter" { - $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" - $destinationPath = "./SomeOtherNonExistingDir/DestinationPath" - try - { - Push-Location $TestDrive - - Expand-Archive -Path $sourcePath -DestinationPath $destinationPath -Force - $expandedFiles = Get-ChildItem $destinationPath -Recurse - $expandedFiles.Length | Should Be 2 - } - finally - { - Pop-Location - } - } - - It "Invoke Expand-Archive with unsupported archive format" { - $sourcePath = "$TestDrive/Sample.cab" - $destinationPath = "$TestDrive/UnsupportedArchiveFormatDir" - try - { - Expand-Archive -Path $sourcePath -DestinationPath $destinationPath -Force - throw "Failed to detect unsupported archive format at $sourcePath" - } - catch - { - $_.FullyQualifiedErrorId | Should Be "NotSupportedArchiveFileExtension,Expand-Archive" - } - } - - It "Invoke Expand-Archive with archive file containing multiple files, directories with subdirectories and empty directories" { - $sourcePath = "$TestDrive/SourceDir" - $archivePath = "$TestDrive/FileAndDirTreeForExpand.zip" - $destinationPath = "$TestDrive/FileAndDirTree" - $sourceList = dir $sourcePath -Name - - Add-CompressionAssemblies - [System.IO.Compression.ZipFile]::CreateFromDirectory($sourcePath, $archivePath) - - Expand-Archive -Path $archivePath -DestinationPath $destinationPath - $extractedList = dir $destinationPath -Name - - Compare-Object -ReferenceObject $extractedList -DifferenceObject $sourceList -PassThru | Should Be $null - } - - It "Validate Expand-Archive cmdlet in pipleline scenario" { - $sourcePath = "$TestDrive/SamplePreCreated*.zip" - $destinationPath = "$TestDrive/PipeToExpandArchive" - - $content = "Some Data" - $files = @("Sample-1.txt", "Sample-2.txt") - - dir $sourcePath | Expand-Archive -DestinationPath $destinationPath - - foreach($currentFile in $files) - { - $expandedFile = Join-Path $destinationPath -ChildPath $currentFile - Test-Path $expandedFile | Should Be $True - Get-Content $expandedFile | Should Be $content - } - } - - It "Validate that Expand-Archive generates Verbose messages" { - $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" - $destinationPath = "$TestDrive/VerboseMessagesInExpandArchive" - - try - { - $ps=[PowerShell]::Create() - $ps.Streams.Error.Clear() - $ps.Streams.Verbose.Clear() - $script = "Import-Module Microsoft.PowerShell.Archive; Expand-Archive -Path $sourcePath -DestinationPath $destinationPath -Verbose" - $ps.AddScript($script) - $ps.Invoke() - - $ps.Streams.Verbose.Count -gt 0 | Should Be $True - $ps.Streams.Error.Count | Should Be 0 - } - finally - { - $ps.Dispose() - } - } - - It "Validate that without -Force parameter Expand-Archive generates non-terminating errors without overwriting existing files" { - $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" - $destinationPath = "$TestDrive/NoForceParameterExpandArchive" - - try - { - $ps=[PowerShell]::Create() - $ps.Streams.Error.Clear() - $ps.Streams.Verbose.Clear() - $script = "Import-Module Microsoft.PowerShell.Archive; Expand-Archive -Path $sourcePath -DestinationPath $destinationPath; Expand-Archive -Path $sourcePath -DestinationPath $destinationPath" - $ps.AddScript($script) - $ps.Invoke() - - $ps.Streams.Error.Count -gt 0 | Should Be $True - } - finally - { - $ps.Dispose() - } - } - - It "Validate that without DestinationPath parameter Expand-Archive cmdlet succeeds in expanding the archive" { - $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" - $archivePath = "$TestDrive/NoDestinationPathParameter.zip" - $destinationPath = "$TestDrive/NoDestinationPathParameter" - copy-item $sourcePath $archivePath -Force - - try - { - Push-Location $TestDrive - - Expand-Archive -Path $archivePath - (dir $destinationPath).Count | Should Be 2 - } - finally - { - Pop-Location - } - } - - It "Validate that without DestinationPath parameter Expand-Archive cmdlet succeeds in expanding the archive when destination directory exists" { - $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" - $archivePath = "$TestDrive/NoDestinationPathParameterDirExists.zip" - $destinationPath = "$TestDrive/NoDestinationPathParameterDirExists" - copy-item $sourcePath $archivePath -Force - New-Item -Path $destinationPath -ItemType Directory | Out-Null - - try - { - Push-Location $TestDrive - - Expand-Archive -Path $archivePath - (dir $destinationPath).Count | Should Be 2 - } - finally - { - Pop-Location - } - } - } -} +<############################################################################################ + # File: Pester.Commands.Cmdlets.ArchiveTests.ps1 + # Commands.Cmdlets.ArchiveTests suite contains Tests that are + # used for validating Microsoft.PowerShell.Archive module. + ############################################################################################> +$script:TestSourceRoot = $PSScriptRoot +Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "CI" { + + AfterAll { + $global:ProgressPreference = $_progressPreference + } + BeforeAll { + # Write-Progress not supported yet on Core + $_progressPreference = $ProgressPreference + if ( $IsCore ) { $global:ProgressPreference = "SilentlyContinue" } + + Setup -d SourceDir + Setup -d SourceDir/ChildDir-1 + Setup -d SourceDir/ChildDir-2 + Setup -d SourceDir/ChildEmptyDir + + $content = "Some Data" + $Files = ( [io.path]::Combine("SourceDir","Sample-1.txt")), ([io.path]::Combine("SourceDir","Sample-2.txt")), + ([io.path]::Combine("SourceDir","ChildDir-1","Sample-3.txt")), ([io.path]::Combine("SourceDir","ChildDir-1","Sample-4.txt")), + ([io.path]::Combine("SourceDir","ChildDir-2","Sample-5.txt")), ([io.path]::Combine("SourceDir","ChildDir-2","Sample-6.txt")) + + foreach($file in $files ) { + Setup -f $file -content $content + } + + Setup -f Sample.unzip -content "Some Text" + Setup -f Sample.cab -content "Some Text" + + $preCreatedArchivePath = Join-Path $script:TestSourceRoot "SamplePreCreatedArchive.archive" + Copy-Item $preCreatedArchivePath $TestDrive/SamplePreCreatedArchive.zip -Force + } + + function Add-CompressionAssemblies { + Add-Type -AssemblyName System.IO.Compression + if (($psedition -eq "Core") -or $IsCore ) + { + Add-Type -AssemblyName System.IO.Compression.ZipFile + } + else + { + Add-Type -AssemblyName System.IO.Compression.FileSystem + } + } + + function CompressArchivePathParameterSetValidator { + param + ( + [string[]] $path, + [string] $destinationPath, + [string] $compressionLevel = "Optimal" + ) + + try + { + Compress-Archive -Path $path -DestinationPath $destinationPath -CompressionLevel $compressionLevel + trow "ValidateNotNullOrEmpty attribute is missing on one of parameters belonging to Path parameterset." + } + catch + { + $_.FullyQualifiedErrorId | Should Be "ParameterArgumentValidationError,Compress-Archive" + } + } + + function CompressArchiveLiteralPathParameterSetValidator { + param + ( + [string[]] $literalPath, + [string] $destinationPath, + [string] $compressionLevel = "Optimal" + ) + + try + { + Compress-Archive -LiteralPath $literalPath -DestinationPath $destinationPath -CompressionLevel $compressionLevel + throw "ValidateNotNullOrEmpty attribute is missing on one of parameters belonging to LiteralPath parameterset." + } + catch + { + $_.FullyQualifiedErrorId | Should Be "ParameterArgumentValidationError,Compress-Archive" + } + } + + + function CompressArchiveInValidPathValidator { + param + ( + [string[]] $path, + [string] $destinationPath, + [string] $invalidPath, + [string] $expectedFullyQualifiedErrorId + ) + + try + { + Compress-Archive -Path $path -DestinationPath $destinationPath + throw "Failed to validate that an invalid Path $invalidPath was supplied as input to Compress-Archive cmdlet." + } + catch + { + $_.FullyQualifiedErrorId | Should Be $expectedFullyQualifiedErrorId + } + } + + function CompressArchiveInValidArchiveFileExtensionValidator { + param + ( + [string[]] $path, + [string] $destinationPath, + [string] $invalidArchiveFileExtension + ) + + try + { + Compress-Archive -Path $path -DestinationPath $destinationPath + throw "Failed to validate that an invalid archive file format $invalidArchiveFileExtension was supplied as input to Compress-Archive cmdlet." + } + catch + { + $_.FullyQualifiedErrorId | Should Be "NotSupportedArchiveFileExtension,Compress-Archive" + } + } + + function Validate-ArchiveEntryCount { + param + ( + [string] $path, + [int] $expectedEntryCount + ) + + Add-CompressionAssemblies + try + { + $archiveFileStreamArgs = @($path, [System.IO.FileMode]::Open) + $archiveFileStream = New-Object -TypeName System.IO.FileStream -ArgumentList $archiveFileStreamArgs + + $zipArchiveArgs = @($archiveFileStream, [System.IO.Compression.ZipArchiveMode]::Read, $false) + $zipArchive = New-Object -TypeName System.IO.Compression.ZipArchive -ArgumentList $zipArchiveArgs + + $actualEntryCount = $zipArchive.Entries.Count + $actualEntryCount | Should Be $expectedEntryCount + } + finally + { + if ($null -ne $zipArchive) { $zipArchive.Dispose()} + if ($null -ne $archiveFileStream) { $archiveFileStream.Dispose() } + } + } + + function ArchiveFileEntryContentValidator { + param + ( + [string] $path, + [string] $entryFileName, + [string] $expectedEntryFileContent + ) + + Add-CompressionAssemblies + try + { + $destFile = "$TestDrive/ExpandedFile"+([System.Guid]::NewGuid().ToString())+".txt" + + $archiveFileStreamArgs = @($path, [System.IO.FileMode]::Open) + $archiveFileStream = New-Object -TypeName System.IO.FileStream -ArgumentList $archiveFileStreamArgs + + $zipArchiveArgs = @($archiveFileStream, [System.IO.Compression.ZipArchiveMode]::Read, $false) + $zipArchive = New-Object -TypeName System.IO.Compression.ZipArchive -ArgumentList $zipArchiveArgs + + $entryToBeUpdated = $zipArchive.Entries | ? {$_.FullName -eq $entryFileName} + + if($entryToBeUpdated -ne $null) + { + $srcStream = $entryToBeUpdated.Open() + $destStream = New-Object "System.IO.FileStream" -ArgumentList( $destFile, [System.IO.FileMode]::Create ) + $srcStream.CopyTo( $destStream ) + $destStream.Dispose() + $srcStream.Dispose() + Get-Content $destFile | Should Be $expectedEntryFileContent + } + else + { + throw "Failed to find the file $entryFileName in the archive file $path" + } + } + finally + { + if ($zipArchive) + { + $zipArchive.Dispose() + } + if ($archiveFileStream) + { + $archiveFileStream.Dispose() + } + } + } + + function ExpandArchiveInvalidParameterValidator { + param + ( + [boolean] $isLiteralPathParameterSet, + [string[]] $path, + [string] $destinationPath, + [string] $expectedFullyQualifiedErrorId + ) + + try + { + if($isLiteralPathParameterSet) + { + Expand-Archive -LiteralPath $literalPath -DestinationPath $destinationPath + } + else + { + Expand-Archive -Path $path -DestinationPath $destinationPath + } + + throw "Expand-Archive did NOT throw expected error" + } + catch + { + $_.FullyQualifiedErrorId | Should Be $expectedFullyQualifiedErrorId + } + } + + Context "Compress-Archive - Parameter validation test cases" { + + It "Validate errors from Compress-Archive with NULL & EMPTY values for Path, LiteralPath, DestinationPath, CompressionLevel parameters" { + $sourcePath = "$TestDrive/SourceDir" + $destinationPath = "$TestDrive/SampleSingleFile.zip" + + CompressArchivePathParameterSetValidator $null $destinationPath + CompressArchivePathParameterSetValidator $sourcePath $null + CompressArchivePathParameterSetValidator $null $null + + CompressArchivePathParameterSetValidator "" $destinationPath + CompressArchivePathParameterSetValidator $sourcePath "" + CompressArchivePathParameterSetValidator "" "" + + CompressArchivePathParameterSetValidator $null $null "NoCompression" + + CompressArchiveLiteralPathParameterSetValidator $null $destinationPath + CompressArchiveLiteralPathParameterSetValidator $sourcePath $null + CompressArchiveLiteralPathParameterSetValidator $null $null + + CompressArchiveLiteralPathParameterSetValidator "" $destinationPath + CompressArchiveLiteralPathParameterSetValidator $sourcePath "" + CompressArchiveLiteralPathParameterSetValidator "" "" + + CompressArchiveLiteralPathParameterSetValidator $null $null "NoCompression" + + CompressArchiveLiteralPathParameterSetValidator $sourcePath $destinationPath $null + CompressArchiveLiteralPathParameterSetValidator $sourcePath $destinationPath "" + } + + It "Validate errors from Compress-Archive when invalid path (non-existing path / non-filesystem path) is supplied for Path or LiteralPath parameters" { + CompressArchiveInValidPathValidator "$TestDrive/InvalidPath" $TestDrive "$TestDrive/InvalidPath" "ArchiveCmdletPathNotFound,Compress-Archive" + if ( ! $IsCore ) { + CompressArchiveInValidPathValidator "HKLM:/SOFTWARE" $TestDrive "HKLM:/SOFTWARE" "PathNotFound,Compress-Archive" + } + CompressArchiveInValidPathValidator "$TestDrive" "$TestDrive/NonExistingDirectory/sample.zip" "$TestDrive/NonExistingDirectory/sample.zip" "ArchiveCmdletPathNotFound,Compress-Archive" + + $path = @("$TestDrive", "$TestDrive/InvalidPath") + CompressArchiveInValidPathValidator $path $TestDrive "$TestDrive/InvalidPath" "ArchiveCmdletPathNotFound,Compress-Archive" + + if ( ! $IsCore ) { + $path = @("$TestDrive", "HKLM:/SOFTWARE") + CompressArchiveInValidPathValidator $path $TestDrive "HKLM:/SOFTWARE" "PathNotFound,Compress-Archive" + } + + $invalidUnZipFileFormat = "$TestDrive/Sample.unzip" + CompressArchiveInValidArchiveFileExtensionValidator $TestDrive "$invalidUnZipFileFormat" ".unzip" + + $invalidcabZipFileFormat = "$TestDrive/Sample.cab" + CompressArchiveInValidArchiveFileExtensionValidator $TestDrive "$invalidcabZipFileFormat" ".cab" + } + + It "Validate error from Compress-Archive when archive file already exists and -Update parameter is not specified" { + $sourcePath = "$TestDrive/SourceDir" + $destinationPath = "$TestDrive/ValidateErrorWhenUpdateNotSpecified.zip" + + try + { + "Some Data" > $destinationPath + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + throw "Failed to validate that an archive file format $destinationPath already exists and -Update switch parameter is not specified while running Compress-Archive command." + } + catch + { + $_.FullyQualifiedErrorId | Should Be "ArchiveFileExists,Compress-Archive" + } + } + + It "Validate error from Compress-Archive when duplicate paths are supplied as input to Path parameter" { + $sourcePath = @( + "$TestDrive/SourceDir/Sample-1.txt", + "$TestDrive/SourceDir/Sample-1.txt") + $destinationPath = "$TestDrive/DuplicatePaths.zip" + + try + { + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + throw "Failed to detect that duplicate Path $sourcePath is supplied as input to Path parameter." + } + catch + { + $_.FullyQualifiedErrorId | Should Be "DuplicatePathFound,Compress-Archive" + } + } + + It "Validate error from Compress-Archive when duplicate paths are supplied as input to LiteralPath parameter" { + $sourcePath = @( + "$TestDrive/SourceDir/Sample-1.txt", + "$TestDrive/SourceDir/Sample-1.txt") + $destinationPath = "$TestDrive/DuplicatePaths.zip" + + try + { + Compress-Archive -LiteralPath $sourcePath -DestinationPath $destinationPath + throw "Failed to detect that duplicate Path $sourcePath is supplied as input to LiteralPath parameter." + } + catch + { + $_.FullyQualifiedErrorId | Should Be "DuplicatePathFound,Compress-Archive" + } + } + + It "Validate that relative path can be specified as Path parameter of Compress-Archive cmdlet" { + $sourcePath = "./SourceDir" + $destinationPath = "RelativePathForPathParameter.zip" + try { + push-location $TESTDRIVE + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + } + finally { + Pop-Location + } + } + It "Validate that relative path can be specified as LiteralPath parameter of Compress-Archive cmdlet" { + $sourcePath = "./SourceDir" + $destinationPath = "RelativePathForLiteralPathParameter.zip" + try { + push-location $TESTDRIVE + Compress-Archive -LiteralPath $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + } + finally { + Pop-Location + } + } + It "Validate that relative path can be specified as DestinationPath parameter of Compress-Archive cmdlet" { + $sourcePath = "$TestDrive/SourceDir" + $destinationPath = "./RelativePathForDestinationPathParameter.zip" + try { + push-location $TESTDRIVE + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + } + finally { + Pop-Location + } + } + } + + Context "Compress-Archive - functional test cases" { + It "Validate that a single file can be compressed using Compress-Archive cmdlet" { + $sourcePath = [io.path]::Combine("$TestDrive","SourceDir","ChildDir-1","Sample-3.txt") + $destinationPath = [io.path]::Combine("$TestDrive","SampleSingleFile.zip") + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + $destinationPath | Should Exist + } + # This test requires a fix in PS5 to support reading paths with square bracket + It "Validate that Compress-Archive cmdlet can accept LiteralPath parameter with Special Characters" -skip:($PSVersionTable.psversion -lt "5.0") { + $sourcePath = "$TestDrive/SourceDir/ChildDir-1/Sample[]File.txt" + "Some Random Content" | Out-File -LiteralPath $sourcePath + $destinationPath = "$TestDrive/SampleSingleFileWithSpecialCharacters.zip" + try + { + Compress-Archive -LiteralPath $sourcePath -DestinationPath $destinationPath + $destinationPath | Should Exist + } + finally + { + get-item -literalPath $sourcePath | remove-Item -force + # Remove-Item -LiteralPath $sourcePath -Force + } + } + It "Validate that Compress-Archive cmdlet errors out when DestinationPath resolves to multiple locations" { + + New-Item $TestDrive/SampleDir/Child-1 -Type Directory -Force | Out-Null + New-Item $TestDrive/SampleDir/Child-2 -Type Directory -Force | Out-Null + New-Item $TestDrive/SampleDir/Test.txt -Type File -Force | Out-Null + + $destinationPath = "$TestDrive/SampleDir/Child-*/SampleChidArchive.zip" + $sourcePath = "$TestDrive/SampleDir/Test.txt" + try + { + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + throw "Failed to detect that destination $destinationPath can resolve to multiple paths" + } + catch + { + $_.FullyQualifiedErrorId | Should Be "InvalidArchiveFilePath,Compress-Archive" + } + finally + { + Remove-Item -LiteralPath $TestDrive/SampleDir -Force -Recurse + } + } + It "Validate that Compress-Archive cmdlet works when DestinationPath has wild card pattern and resolves to a single valid path" { + + New-Item $TestDrive/SampleDir/Child-1 -Type Directory -Force | Out-Null + New-Item $TestDrive/SampleDir/Test.txt -Type File -Force | Out-Null + + $destinationPath = "$TestDrive/SampleDir/Child-*/SampleChidArchive.zip" + $sourcePath = "$TestDrive/SampleDir/Test.txt" + try + { + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + $destinationPath | Should Exist + } + finally + { + Remove-Item -LiteralPath $TestDrive/SampleDir -Force -Recurse + } + } + # This test requires a fix in PS5 to support reading paths with square bracket + It "Validate that Compress-Archive cmdlet can accept LiteralPath parameter for a directory with Special Characters in the directory name" -skip:($PSVersionTable.psversion -lt "5.0") { + $sourcePath = "$TestDrive/Source[]Dir/ChildDir[]-1" + New-Item $sourcePath -Type Directory | Out-Null + "Some Random Content" | Out-File -LiteralPath "$sourcePath/Sample[]File.txt" + $destinationPath = "$TestDrive/SampleDirWithSpecialCharacters.zip" + try + { + Compress-Archive -LiteralPath $sourcePath -DestinationPath $destinationPath + $destinationPath | Should Exist + } + finally + { + get-item -LiteralPath $sourcePath | Remove-Item -Force -Recurse + # Remove-Item -LiteralPath $sourcePath -Force -Recurse + } + } + It "Validate that Compress-Archive cmdlet can accept DestinationPath parameter with Special Characters" { + $sourcePath = "$TestDrive/SourceDir/ChildDir-1/Sample-3.txt" + $destinationPath = "$TestDrive/Sample[]SingleFile.zip" + try + { + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path -LiteralPath $destinationPath | Should Be $true + } + finally + { + Get-Item -LiteralPath $destinationPath | Remove-Item -Force + # Remove-Item -LiteralPath $destinationPath -Force + } + } + It "Validate that Source Path can be at SystemDrive location" -skip:($IsCore) { + $sourcePath = "$env:SystemDrive/SourceDir" + $destinationPath = "$TestDrive/SampleFromSystemDrive.zip" + New-Item $sourcePath -Type Directory | Out-Null + "Some Data" | Out-File -FilePath $sourcePath/SampleSourceFileForArchive.txt + try + { + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + } + finally + { + remove-item "$sourcePath" -Force -Recurse -ErrorAction SilentlyContinue + } + } + It "Validate that multiple files can be compressed using Compress-Archive cmdlet" { + $sourcePath = @( + "$TestDrive/SourceDir/ChildDir-1/Sample-3.txt", + "$TestDrive/SourceDir/ChildDir-1/Sample-4.txt", + "$TestDrive/SourceDir/ChildDir-2/Sample-5.txt", + "$TestDrive/SourceDir/ChildDir-2/Sample-6.txt") + $destinationPath = "$TestDrive/SampleMultipleFiles.zip" + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + } + It "Validate that multiple files and directories can be compressed using Compress-Archive cmdlet" { + $sourcePath = @( + "$TestDrive/SourceDir/Sample-1.txt", + "$TestDrive/SourceDir/Sample-2.txt", + "$TestDrive/SourceDir/ChildDir-1", + "$TestDrive/SourceDir/ChildDir-2") + $destinationPath = "$TestDrive/SampleMultipleFilesAndDirs.zip" + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + } + It "Validate that a single directory can be compressed using Compress-Archive cmdlet" { + $sourcePath = @("$TestDrive/SourceDir/ChildDir-1") + $destinationPath = "$TestDrive/SampleSingleDir.zip" + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + } + It "Validate that a single directory with multiple files and subdirectories can be compressed using Compress-Archive cmdlet" { + $sourcePath = @("$TestDrive/SourceDir") + $destinationPath = "$TestDrive/SampleSubTree.zip" + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + } + It "Validate that a single directory & multiple files can be compressed using Compress-Archive cmdlet" { + $sourcePath = @( + "$TestDrive/SourceDir/ChildDir-1", + "$TestDrive/SourceDir/Sample-1.txt", + "$TestDrive/SourceDir/Sample-2.txt") + $destinationPath = "$TestDrive/SampleMultipleFilesAndSingleDir.zip" + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + } + + It "Validate that if .zip extension is not supplied as input to DestinationPath parameter, then .zip extension is appended" { + $sourcePath = @("$TestDrive/SourceDir") + $destinationPath = "$TestDrive/SampleNoExtension.zip" + $destinationWithoutExtensionPath = "$TestDrive/SampleNoExtension" + Compress-Archive -Path $sourcePath -DestinationPath $destinationWithoutExtensionPath + Test-Path $destinationPath | Should Be $true + } + + It "Validate that -Update parameter makes Compress-Archive to not throw an error if archive file already exists" { + $sourcePath = @("$TestDrive/SourceDir") + $destinationPath = "$TestDrive/SampleUpdateTest.zip" + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -Update + Test-Path $destinationPath | Should Be $true + } + It "Validate -Update parameter by adding a new file to an existing archive file" { + $sourcePath = @("$TestDrive/SourceDir/ChildDir-1") + $destinationPath = "$TestDrive/SampleUpdateAdd1File.zip" + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + New-Item $TestDrive/SourceDir/ChildDir-1/Sample-AddedNewFile.txt -Type File | Out-Null + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -Update + Test-Path $destinationPath | Should Be $true + Validate-ArchiveEntryCount -path $destinationPath -expectedEntryCount 3 + } + + It "Validate that all CompressionLevel values can be used with Compress-Archive cmdlet" { + $sourcePath = "$TestDrive/SourceDir/Sample-1.txt" + + $destinationPath = "$TestDrive/FastestCompressionLevel.zip" + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -CompressionLevel Fastest + Test-Path $destinationPath | Should Be $true + + $destinationPath = "$TestDrive/OptimalCompressionLevel.zip" + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -CompressionLevel Optimal + Test-Path $destinationPath | Should Be $true + + $destinationPath = "$TestDrive/NoCompressionCompressionLevel.zip" + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -CompressionLevel NoCompression + Test-Path $destinationPath | Should Be $true + } + + It "Validate that -Update parameter is modifying a file that already exists in the archive file" { + $filePath = "$TestDrive/SourceDir/ChildDir-1/Sample-3.txt" + + $initialContent = "Initial Content" + $modifiedContent = "Modified Content" + + $initialContent | Set-Content $filePath + + $sourcePath = "$TestDrive/SourceDir" + $destinationPath = "$TestDrive/UpdatingModifiedFile.zip" + + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $True + + $modifiedContent | Set-Content $filePath + + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -Update + Test-Path $destinationPath | Should Be $True + + ArchiveFileEntryContentValidator "$destinationPath" ([io.path]::Combine("SourceDir","ChildDir-1","Sample-3.txt")) $modifiedContent + } + + It "Validate Compress-Archive cmdlet in pipleline scenario" { + $destinationPath = "$TestDrive/CompressArchiveFromPipeline.zip" + + # Piping a single file path to Compress-Archive + dir -Path $TestDrive/SourceDir/Sample-1.txt | Compress-Archive -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $True + + # Piping a string directory path to Compress-Archive + "$TestDrive/SourceDir/ChildDir-2" | Compress-Archive -DestinationPath $destinationPath -Update + Test-Path $destinationPath | Should Be $True + + # Piping the output of Get-ChildItem to Compress-Archive + dir "$TestDrive/SourceDir" -Recurse | Compress-Archive -DestinationPath $destinationPath -Update + Test-Path $destinationPath | Should Be $True + } + + It "Validate that Compress-Archive works on ReadOnly files" { + $sourcePath = "$TestDrive/ReadOnlyFile.txt" + $destinationPath = "$TestDrive/TestForReadOnlyFile.zip" + + "Some Content" | Out-File -FilePath $sourcePath + $createdItem = Get-Item $sourcePath + $createdItem.Attributes = 'ReadOnly' + + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + } + + It "Validate that Compress-Archive generates Verbose messages" { + $sourcePath = "$TestDrive/SourceDir" + $destinationPath = "$TestDrive/Compress-Archive generates VerboseMessages.zip" + + try + { + $ps=[PowerShell]::Create() + $ps.Streams.Error.Clear() + $ps.Streams.Verbose.Clear() + $script = "Import-Module Microsoft.PowerShell.Archive; Compress-Archive -Path $sourcePath -DestinationPath `"$destinationPath`" -CompressionLevel Fastest -Verbose" + $ps.AddScript($script) + $ps.Invoke() + + $ps.Streams.Verbose.Count -gt 0 | Should Be $True + $ps.Streams.Error.Count | Should Be 0 + } + finally + { + $ps.Dispose() + } + } + } + + Context "Expand-Archive - Parameter validation test cases" { + It "Validate non existing archive -Path trows expected error message" { + $sourcePath = "$TestDrive/SourceDir" + $destinationPath = "$TestDrive/ExpandedArchive" + try + { + Expand-Archive -Path $sourcePath -DestinationPath $destinationPath + throw "Expand-Archive succeeded for non existing archive path" + } + catch + { + $_.FullyQualifiedErrorId | Should Be "PathNotFound,Expand-Archive" + } + } + + It "Validate errors from Expand-Archive with NULL & EMPTY values for Path, LiteralPath, DestinationPath parameters" { + ExpandArchiveInvalidParameterValidator $false $null "$TestDrive/SourceDir" "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $false $null $null "ParameterArgumentValidationError,Expand-Archive" + + ExpandArchiveInvalidParameterValidator $false "$TestDrive/SourceDir" $null "ParameterArgumentTransformationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $false "" "$TestDrive/SourceDir" "ParameterArgumentTransformationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $false "$TestDrive/SourceDir" "" "ParameterArgumentTransformationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $false "" "" "ParameterArgumentTransformationError,Expand-Archive" + + ExpandArchiveInvalidParameterValidator $true $null "$TestDrive/SourceDir" "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $true $null $null "ParameterArgumentValidationError,Expand-Archive" + + ExpandArchiveInvalidParameterValidator $true "$TestDrive/SourceDir" $null "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $true "" "$TestDrive/SourceDir" "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $true "$TestDrive/SourceDir" "" "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $true "" "" "ParameterArgumentValidationError,Expand-Archive" + + ExpandArchiveInvalidParameterValidator $true $null "$TestDrive/SourceDir" "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $true $null $null "ParameterArgumentValidationError,Expand-Archive" + + ExpandArchiveInvalidParameterValidator $true "$TestDrive/SourceDir" $null "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $true "" "$TestDrive/SourceDir" "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $true "$TestDrive/SourceDir" "" "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $true "" "" "ParameterArgumentValidationError,Expand-Archive" + } + + It "Validate errors from Expand-Archive when invalid path (non-existing path / non-filesystem path) is supplied for Path or LiteralPath parameters" { + try { Expand-Archive -Path "$TestDrive/NonExistingArchive" -DestinationPath "$TestDrive/SourceDir"; throw "Expand-Archive did NOT throw expected error" } + catch { $_.FullyQualifiedErrorId | Should Be "ArchiveCmdletPathNotFound,Expand-Archive" } + + if ( ! $IsCore ) { + try { Expand-Archive -Path "HKLM:/SOFTWARE" -DestinationPath "$TestDrive/SourceDir"; throw "Expand-Archive did NOT throw expected error" } + catch { $_.FullyQualifiedErrorId | Should Be "PathNotFound,Expand-Archive" } + } + + try { Expand-Archive -LiteralPath "$TestDrive/NonExistingArchive" -DestinationPath "$TestDrive/SourceDir"; throw "Expand-Archive did NOT throw expected error" } + catch { $_.FullyQualifiedErrorId | Should Be "ArchiveCmdletPathNotFound,Expand-Archive" } + + if ( ! $IsCore ) { + try { Expand-Archive -LiteralPath "HKLM:/SOFTWARE" -DestinationPath "$TestDrive/SourceDir"; throw "Expand-Archive did NOT throw expected error" } + catch { $_.FullyQualifiedErrorId | Should Be "PathNotFound,Expand-Archive" } + } + } + + It "Validate error from Expand-Archive when invalid path (non-existing path / non-filesystem path) is supplied for DestinationPath parameter" { + $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" + # $destinationPath = "HKLM:/SOFTWARE" + $destinationPath = "Variable:/" + + try { Expand-Archive -Path $sourcePath -DestinationPath $destinationPath; throw "Expand-Archive did NOT throw expected error" } + catch { $_.FullyQualifiedErrorId | Should Be "InvalidDirectoryPath,Expand-Archive" } + } + } + + Context "Expand-Archive - functional test cases" { + It "Validate basic Expand-Archive scenario" { + $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" + $content = "Some Data" + $destinationPath = "$TestDrive/DestDirForBasicExpand" + $files = @("Sample-1.txt", "Sample-2.txt") + + # The files in "$TestDrive/SamplePreCreatedArchive.zip" are precreated. + $fileCreationTimeStamp = Get-Date -Year 2014 -Month 6 -Day 13 -Hour 15 -Minute 50 -Second 20 -Millisecond 0 + + Expand-Archive -Path $sourcePath -DestinationPath $destinationPath + foreach($currentFile in $files) + { + $expandedFile = Join-Path $destinationPath -ChildPath $currentFile + Test-Path $expandedFile | Should Be $True + + # We are validating to make sure that time stamps are preserved in the + # compressed archive are reflected back when the file is expanded. + (dir $expandedFile).LastWriteTime.CompareTo($fileCreationTimeStamp) | Should Be 0 + + Get-Content $expandedFile | Should Be $content + } + } + It "Validate that Expand-Archive cmdlet errors out when DestinationPath resolves to multiple locations" { + $testbasename = "TargetDir" + setup -d "$testbasename" + setup -d "$testbasename/Child-1" + setup -d "$testbasename/Child-2" + + $destinationPath = [io.path]::Combine("$TestDrive","$testbasename","Child-*") + $sourcePath = join-path "$TestDrive" "SamplePreCreatedArchive.zip" + try + { + Expand-Archive -Path $sourcePath -DestinationPath $destinationPath + throw "Failed to detect that destination $destinationPath can resolve to multiple paths" + } + catch + { + $_.FullyQualifiedErrorId | Should Be "InvalidDestinationPath,Expand-Archive" + } + finally + { + Remove-Item -LiteralPath "$TestDrive/$testbasename" -Force -Recurse + } + } + It "Validate that Expand-Archive cmdlet works when DestinationPath resolves has wild card pattern and resolves to a single valid path" { + $testbasename = "TargetDir" + setup -d "$testbasename" + setup -d "$testbasename/Child-1" + + $destinationPath = [io.path]::Combine("$TestDrive","$testbasename","Child-*") + $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" + try + { + Expand-Archive -Path $sourcePath -DestinationPath $destinationPath + $expandedFiles = Get-ChildItem $destinationPath -Recurse + $expandedFiles.Length | Should BeGreaterThan 1 + } + finally + { + Remove-Item -LiteralPath "$TestDrive/$testbasename" -Force -Recurse + } + } + It "Validate Expand-Archive scenario where DestinationPath has Special Characters" { + $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" + $content = "Some Data" + $destinationPath = "$TestDrive/DestDir[]Expand" + $files = @("Sample-1.txt", "Sample-2.txt") + + # The files in "$TestDrive/SamplePreCreatedArchive.zip" are precreated. + $fileCreationTimeStamp = Get-Date -Year 2014 -Month 6 -Day 13 -Hour 15 -Minute 50 -Second 20 -Millisecond 0 + + Expand-Archive -Path $sourcePath -DestinationPath $destinationPath + foreach($currentFile in $files) + { + $expandedFile = Join-Path $destinationPath -ChildPath $currentFile + Test-Path -LiteralPath $expandedFile | Should Be $True + + # We are validating to make sure that time stamps are preserved in the + # compressed archive are reflected back when the file is expanded. + (dir -LiteralPath $expandedFile).LastWriteTime.CompareTo($fileCreationTimeStamp) | Should Be 0 + + Get-Content -LiteralPath $expandedFile | Should Be $content + } + } + It "Invoke Expand-Archive with relative path in Path parameter and -Force parameter" { + $sourcePath = "./SamplePreCreatedArchive.zip" + $destinationPath = "$TestDrive/SomeOtherNonExistingDir/Path" + try + { + Push-Location $TestDrive + + Expand-Archive -Path $sourcePath -DestinationPath $destinationPath -Force + $expandedFiles = Get-ChildItem $destinationPath -Recurse + $expandedFiles.Length | Should Be 2 + } + finally + { + Pop-Location + } + } + + It "Invoke Expand-Archive with relative path in LiteralPath parameter and -Force parameter" { + $sourcePath = "./SamplePreCreatedArchive.zip" + $destinationPath = "$TestDrive/SomeOtherNonExistingDir/LiteralPath" + try + { + Push-Location $TestDrive + + Expand-Archive -LiteralPath $sourcePath -DestinationPath $destinationPath -Force + $expandedFiles = Get-ChildItem $destinationPath -Recurse + $expandedFiles.Length | Should Be 2 + } + finally + { + Pop-Location + } + } + + It "Invoke Expand-Archive with non-existing relative directory in DestinationPath parameter and -Force parameter" { + $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" + $destinationPath = "./SomeOtherNonExistingDir/DestinationPath" + try + { + Push-Location $TestDrive + + Expand-Archive -Path $sourcePath -DestinationPath $destinationPath -Force + $expandedFiles = Get-ChildItem $destinationPath -Recurse + $expandedFiles.Length | Should Be 2 + } + finally + { + Pop-Location + } + } + + It "Invoke Expand-Archive with unsupported archive format" { + $sourcePath = "$TestDrive/Sample.cab" + $destinationPath = "$TestDrive/UnsupportedArchiveFormatDir" + try + { + Expand-Archive -Path $sourcePath -DestinationPath $destinationPath -Force + throw "Failed to detect unsupported archive format at $sourcePath" + } + catch + { + $_.FullyQualifiedErrorId | Should Be "NotSupportedArchiveFileExtension,Expand-Archive" + } + } + + It "Invoke Expand-Archive with archive file containing multiple files, directories with subdirectories and empty directories" { + $sourcePath = "$TestDrive/SourceDir" + $archivePath = "$TestDrive/FileAndDirTreeForExpand.zip" + $destinationPath = "$TestDrive/FileAndDirTree" + $sourceList = dir $sourcePath -Name + + Add-CompressionAssemblies + [System.IO.Compression.ZipFile]::CreateFromDirectory($sourcePath, $archivePath) + + Expand-Archive -Path $archivePath -DestinationPath $destinationPath + $extractedList = dir $destinationPath -Name + + Compare-Object -ReferenceObject $extractedList -DifferenceObject $sourceList -PassThru | Should Be $null + } + + It "Validate Expand-Archive cmdlet in pipleline scenario" { + $sourcePath = "$TestDrive/SamplePreCreated*.zip" + $destinationPath = "$TestDrive/PipeToExpandArchive" + + $content = "Some Data" + $files = @("Sample-1.txt", "Sample-2.txt") + + dir $sourcePath | Expand-Archive -DestinationPath $destinationPath + + foreach($currentFile in $files) + { + $expandedFile = Join-Path $destinationPath -ChildPath $currentFile + Test-Path $expandedFile | Should Be $True + Get-Content $expandedFile | Should Be $content + } + } + + It "Validate that Expand-Archive generates Verbose messages" { + $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" + $destinationPath = "$TestDrive/VerboseMessagesInExpandArchive" + + try + { + $ps=[PowerShell]::Create() + $ps.Streams.Error.Clear() + $ps.Streams.Verbose.Clear() + $script = "Import-Module Microsoft.PowerShell.Archive; Expand-Archive -Path $sourcePath -DestinationPath $destinationPath -Verbose" + $ps.AddScript($script) + $ps.Invoke() + + $ps.Streams.Verbose.Count -gt 0 | Should Be $True + $ps.Streams.Error.Count | Should Be 0 + } + finally + { + $ps.Dispose() + } + } + + It "Validate that without -Force parameter Expand-Archive generates non-terminating errors without overwriting existing files" { + $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" + $destinationPath = "$TestDrive/NoForceParameterExpandArchive" + + try + { + $ps=[PowerShell]::Create() + $ps.Streams.Error.Clear() + $ps.Streams.Verbose.Clear() + $script = "Import-Module Microsoft.PowerShell.Archive; Expand-Archive -Path $sourcePath -DestinationPath $destinationPath; Expand-Archive -Path $sourcePath -DestinationPath $destinationPath" + $ps.AddScript($script) + $ps.Invoke() + + $ps.Streams.Error.Count -gt 0 | Should Be $True + } + finally + { + $ps.Dispose() + } + } + + It "Validate that without DestinationPath parameter Expand-Archive cmdlet succeeds in expanding the archive" { + $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" + $archivePath = "$TestDrive/NoDestinationPathParameter.zip" + $destinationPath = "$TestDrive/NoDestinationPathParameter" + copy-item $sourcePath $archivePath -Force + + try + { + Push-Location $TestDrive + + Expand-Archive -Path $archivePath + (dir $destinationPath).Count | Should Be 2 + } + finally + { + Pop-Location + } + } + + It "Validate that without DestinationPath parameter Expand-Archive cmdlet succeeds in expanding the archive when destination directory exists" { + $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" + $archivePath = "$TestDrive/NoDestinationPathParameterDirExists.zip" + $destinationPath = "$TestDrive/NoDestinationPathParameterDirExists" + copy-item $sourcePath $archivePath -Force + New-Item -Path $destinationPath -ItemType Directory | Out-Null + + try + { + Push-Location $TestDrive + + Expand-Archive -Path $archivePath + (dir $destinationPath).Count | Should Be 2 + } + finally + { + Pop-Location + } + } + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Core/History.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Core/History.Tests.ps1 index 4dd0e2b1b1..054e08f1f3 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Core/History.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Core/History.Tests.ps1 @@ -1,64 +1,64 @@ -Describe "History cmdlet test cases" -Tags "CI" { - - It "Tests Invoke-History on a cmdlet that generates output on all streams" { - $streamSpammer = ' - function StreamSpammer - { - [CmdletBinding()] - param() - - Write-Debug "Debug" - Write-Error "Error" - Write-Information "Information" - Write-Progress "Progress" - Write-Verbose "Verbose" - Write-Warning "Warning" - "Output" - } - - $informationPreference = "Continue" - $debugPreference = "Continue" - $verbosePreference = "Continue" - ' - - $invocationSettings = New-Object System.Management.Automation.PSInvocationSettings - $invocationSettings.AddToHistory = $true - $ps = [PowerShell]::Create() - $null = $ps.AddScript($streamSpammer).Invoke() - $ps.Commands.Clear() - $null = $ps.AddScript("StreamSpammer"); - $null = $ps.Invoke($null, $invocationSettings) - $ps.Commands.Clear() - $null = $ps.AddScript("Invoke-History -id 1") - $result = $ps.Invoke($null, $invocationSettings) - $outputCount = $( - $ps.Streams.Error; - $ps.Streams.Progress; - $ps.Streams.Verbose; - $ps.Streams.Debug; - $ps.Streams.Warning; - $ps.Streams.Information).Count - $ps.Dispose() - - ## Twice per stream - once for the original invocatgion, and once for the re-invocation - $outputCount | Should be 12 - } - - It "Tests Invoke-History on a private command" { - - $invocationSettings = New-Object System.Management.Automation.PSInvocationSettings - $invocationSettings.AddToHistory = $true - $ps = [PowerShell]::Create() - $null = $ps.AddScript("(Get-Command Get-Process).Visibility = 'Private'").Invoke() - $ps.Commands.Clear() - $null = $ps.AddScript("Get-Process -id $pid") - $null = $ps.Invoke($null, $invocationSettings) - $ps.Commands.Clear() - $null = $ps.AddScript("Invoke-History -id 1") - $result = $ps.Invoke($null, $invocationSettings) - $errorResult = $ps.Streams.Error[0].FullyQualifiedErrorId - $ps.Dispose() - - $errorResult | Should be CommandNotFoundException - } -} +Describe "History cmdlet test cases" -Tags "CI" { + + It "Tests Invoke-History on a cmdlet that generates output on all streams" { + $streamSpammer = ' + function StreamSpammer + { + [CmdletBinding()] + param() + + Write-Debug "Debug" + Write-Error "Error" + Write-Information "Information" + Write-Progress "Progress" + Write-Verbose "Verbose" + Write-Warning "Warning" + "Output" + } + + $informationPreference = "Continue" + $debugPreference = "Continue" + $verbosePreference = "Continue" + ' + + $invocationSettings = New-Object System.Management.Automation.PSInvocationSettings + $invocationSettings.AddToHistory = $true + $ps = [PowerShell]::Create() + $null = $ps.AddScript($streamSpammer).Invoke() + $ps.Commands.Clear() + $null = $ps.AddScript("StreamSpammer"); + $null = $ps.Invoke($null, $invocationSettings) + $ps.Commands.Clear() + $null = $ps.AddScript("Invoke-History -id 1") + $result = $ps.Invoke($null, $invocationSettings) + $outputCount = $( + $ps.Streams.Error; + $ps.Streams.Progress; + $ps.Streams.Verbose; + $ps.Streams.Debug; + $ps.Streams.Warning; + $ps.Streams.Information).Count + $ps.Dispose() + + ## Twice per stream - once for the original invocatgion, and once for the re-invocation + $outputCount | Should be 12 + } + + It "Tests Invoke-History on a private command" { + + $invocationSettings = New-Object System.Management.Automation.PSInvocationSettings + $invocationSettings.AddToHistory = $true + $ps = [PowerShell]::Create() + $null = $ps.AddScript("(Get-Command Get-Process).Visibility = 'Private'").Invoke() + $ps.Commands.Clear() + $null = $ps.AddScript("Get-Process -id $pid") + $null = $ps.Invoke($null, $invocationSettings) + $ps.Commands.Clear() + $null = $ps.AddScript("Invoke-History -id 1") + $result = $ps.Invoke($null, $invocationSettings) + $errorResult = $ps.Streams.Error[0].FullyQualifiedErrorId + $ps.Dispose() + + $errorResult | Should be CommandNotFoundException + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Core/Pester.Commands.Cmdlets.GetCommand.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Core/Pester.Commands.Cmdlets.GetCommand.Tests.ps1 index 0c99c42702..ce3511946f 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Core/Pester.Commands.Cmdlets.GetCommand.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Core/Pester.Commands.Cmdlets.GetCommand.Tests.ps1 @@ -1,52 +1,52 @@ -## -## Copyright (c) Microsoft Corporation, 2015 -## - -Describe "Tests Get-Command with relative paths and wildcards" -Tag "CI" { - - BeforeAll { - # Create temporary EXE command files - $file1 = Setup -f WildCardCommandA.exe -pass - $file2 = Setup -f WildCardCommand[B].exe -pass - #$null = New-Item -ItemType File -Path (Join-Path $TestDrive WildCardCommandA.exe) -ErrorAction Ignore - #$null = New-Item -ItemType File -Path (Join-Path $TestDRive WildCardCommand[B].exe) -ErrorAction Ignore - if ( $IsLinux -or $IsOSX ) { - /bin/chmod 777 "$file1" - /bin/chmod 777 "$file2" - } - } - - It "Test wildcard with drive relative directory path" { - $pathName = Join-Path $TestDrive "WildCardCommandA*" - $driveOffset = $pathName.IndexOf(":") - $pathName = $pathName.Substring($driveOffset + 1) - $result = Get-Command -Name $pathName - $result | Should Not Be $null - $result.Name | Should Be WildCardCommandA.exe - } - - It "Test wildcard with relative directory path" { - push-location $TestDrive - $result = Get-Command -Name .\WildCardCommandA* - pop-location - $result | Should Not Be $null - $result | Should Be WildCardCommandA.exe - } - - It "Test with PowerShell wildcard and relative path" { - push-location $TestDrive - - # This should use the wildcard to find WildCardCommandA.exe - $result = Get-Command -Name .\WildCardCommand[A].exe - $result | Should Not Be $null - $result | Should Be WildCardCommandA.exe - - # This should find the file WildCardCommand[B].exe - $result = Get-Command -Name .\WildCardCommand[B].exe - $result | Should Not Be $null - $result | Should Be WildCardCommand[B].exe - - Pop-Location - } - -} +## +## Copyright (c) Microsoft Corporation, 2015 +## + +Describe "Tests Get-Command with relative paths and wildcards" -Tag "CI" { + + BeforeAll { + # Create temporary EXE command files + $file1 = Setup -f WildCardCommandA.exe -pass + $file2 = Setup -f WildCardCommand[B].exe -pass + #$null = New-Item -ItemType File -Path (Join-Path $TestDrive WildCardCommandA.exe) -ErrorAction Ignore + #$null = New-Item -ItemType File -Path (Join-Path $TestDRive WildCardCommand[B].exe) -ErrorAction Ignore + if ( $IsLinux -or $IsOSX ) { + /bin/chmod 777 "$file1" + /bin/chmod 777 "$file2" + } + } + + It "Test wildcard with drive relative directory path" { + $pathName = Join-Path $TestDrive "WildCardCommandA*" + $driveOffset = $pathName.IndexOf(":") + $pathName = $pathName.Substring($driveOffset + 1) + $result = Get-Command -Name $pathName + $result | Should Not Be $null + $result.Name | Should Be WildCardCommandA.exe + } + + It "Test wildcard with relative directory path" { + push-location $TestDrive + $result = Get-Command -Name .\WildCardCommandA* + pop-location + $result | Should Not Be $null + $result | Should Be WildCardCommandA.exe + } + + It "Test with PowerShell wildcard and relative path" { + push-location $TestDrive + + # This should use the wildcard to find WildCardCommandA.exe + $result = Get-Command -Name .\WildCardCommand[A].exe + $result | Should Not Be $null + $result | Should Be WildCardCommandA.exe + + # This should find the file WildCardCommand[B].exe + $result = Get-Command -Name .\WildCardCommand[B].exe + $result | Should Not Be $null + $result | Should Be WildCardCommand[B].exe + + Pop-Location + } + +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Copy.Item.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Copy.Item.Tests.ps1 index dd1c13a738..49f4e7cfab 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Copy.Item.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Copy.Item.Tests.ps1 @@ -1,868 +1,868 @@ -# This is a Pester test suite to validate Copy-Item remotely using a remote session. -# -# Copyright (c) Microsoft Corporation, 2015 -# -# - -# If PS Remoting is not available, do not run the suite. -function ShouldRun -{ - if ( $IsCore ) { return $false } - $result = Invoke-Command -ComputerName . -ScriptBlock {1} -ErrorAction SilentlyContinue - return ($result -eq 1) -} - -if (-not (ShouldRun)) -{ - Write-Host "PS Remoting is not available, skipping tests..." -ForegroundColor Cyan - return -} - -Describe "Validate Copy-Item Remotely" -Tags "CI" { - - # Validate a copy item operation. - # $filePath is the source file path - # - function ValidateCopyItemOperation - { - param ([string]$filePath, [string]$destination) - - if (-not $destination) - { - $copiedFilePath = ([string]$filePath).Replace("SourceDirectory", "DestinationDirectory") - } - else - { - $fileName = Split-Path $filePath -Leaf - $copiedFilePath = Join-Path $destination $fileName - } - - $copiedFilePath | should Exist - - # Validate file attributes - $originalFile = Get-Item $filePath -Force - $newFile = Get-Item $copiedFilePath -Force - - # Validate file Length - $newFile.Length | should be $originalFile.Length - - # Validate LastWriteTime - $newFile.LastWriteTime | should be $originalFile.LastWriteTime - $newFile.LastWriteTimeUtc | should be $originalFile.LastWriteTimeUtc - - # Validate Attributes - $newFile.Attributes.value__ | Should Be $originalFile.Attributes.value__ - } - - # Validate a copy item operation. - # $filePath is the source file path - # - function ValidateCopyItemOperationForAlternateDataStream - { - param ([string]$filePath, $streamName, $expectedStreamContent) - - $copiedFilePath = ([string]$filePath).Replace("SourceDirectory", "DestinationDirectory") - $copiedFilePath | should Exist - (Get-Item $copiedFilePath).Length | should be (Get-Item $filePath).Length - - # Validate the stream - $actualStreamContent = Get-Content -Path $copiedFilePath -Stream $streamName -ea SilentlyContinue - $actualStreamContent | Should Match $expectedStreamContent - } - - BeforeAll { - $s = New-PSSession -ComputerName . -ea SilentlyContinue - if (-not $s) - { - throw "Failed to create PSSession for remote copy operations." - } - - $destinationFolderName = "DestinationDirectory" - $sourceFolderName = "SourceDirectory" - $testDirectory = Join-Path "TestDrive:" "copyItemRemotely" - $destinationDirectory = Join-Path $testDirectory $destinationFolderName - $sourceDirectory = Join-Path $testDirectory $sourceFolderName - - # Creates one txt file - # - function CreateTestFile - { - param ([switch]$setReadOnlyAttribute = $false, [switch]$emptyFile = $false) - - # Create the test directory. - New-Item -Path $sourceDirectory -Force -ItemType Directory | Out-Null - - # Create the file. - $filePath = Join-Path $sourceDirectory "testfileone.txt" - if (-not $emptyFile) - { - "File test content" | Out-File $filePath -Force - } - else - { - "" | Out-File $filePath -Force - } - - if (-not (Test-Path $filePath)) - { - throw "Failed to create test file $filePath." - } - - if ($setReadOnlyAttribute) - { - Set-ItemProperty $filePath -Name IsReadOnly -value $true -Force - } - - return (Get-Item $filePath).FullName - } - - # Create a set of directories and files with the following structure: - # .\copyItemRemotely\SourceDirectory\A\a.txt - # .\copyItemRemotely\SourceDirectory\A\a2.txt - # .\copyItemRemotely\SourceDirectory\rootFile.txt - # .\copyItemRemotely\SourceDirectory\B\b.txt - # .\copyItemRemotely\SourceDirectory\C\D\d.txt - # - function CreateTestDirectory - { - param ([switch]$setReadOnlyAttribute = $false) - - $directoriesToCreate = @() - $directoriesToCreate += "A" - $directoriesToCreate += "B" - $directoriesToCreate += "C\D" - - $filesToCreate = @() - $filesToCreate += "rootFile.txt" - $filesToCreate += "A\a.txt" - $filesToCreate += "A\a2.txt" - $filesToCreate += "B\b.txt" - $filesToCreate += "C\D\d.txt" - - # Create the directories. - foreach ($directory in $directoriesToCreate) - { - $directoryPath = Join-Path $sourceDirectory $directory - New-Item -Path $directoryPath -Force -ItemType Directory | Out-Null - } - - $result = @{ - SourceDirectory = (Get-Item $sourceDirectory).FullName - Files = @() - } - - # Create the files. - foreach ($file in $filesToCreate) - { - $filePath = Join-Path $sourceDirectory $file - $file + "`r`n File test content" | Out-File $filePath -Force - - if (-not (Test-Path $filePath)) - { - throw "Failed to create test file $filePath." - } - - if ($setReadOnlyAttribute) - { - Set-ItemProperty $filePath -Name IsReadOnly -value $true -Force - } - - $result.Files += (Get-Item $filePath).FullName - } - - return $result - } - - function GenerateTestAssembly - { - $assemblyPath = Join-Path $env:TEMP TestModule - $outputPath = Join-Path $assemblyPath TestModule.dll - - if (-not (Test-Path $assemblyPath)) - { - New-Item $assemblyPath -Force -ItemType Directory | Out-Null - } - - if (-not (Test-Path $outputPath)) - { - $code = @" - namespace TestModule - { - using System; - using System.Management.Automation; - - [Cmdlet(VerbsCommon.Get, "TestModule")] - public class TestSameCmdlets : PSCmdlet - { - protected override void ProcessRecord() - { - WriteObject("TestModule"); - } - } - } -"@ - Add-Type -TypeDefinition $code -OutputAssembly $outputPath - } - - $result = @{ - ModuleName = "TestModule" - Path = (Get-Item $outputPath).FullName - } - - return $result - } - - function GetDestinationFolderPath - { - return (Get-Item $destinationDirectory).FullName - } - } - - AfterAll { - Remove-PSSession -Name $s.Name -ea SilentlyContinue - } - - BeforeEach { - <# Ensure we start with an empty test directory. Here is the file structure - - $destinationFolderName = "DestinationDirectory" - $sourceFolderName = "SourceDirectory" - $testDirectory = Join-Path "TestDrive:" "copyItemRemotely" - $destinationDirectory = Join-Path $testDirectory $destinationFolderName - $sourceDirectory = Join-Path $testDirectory $sourceFolderName - #> - - if (test-path $testDirectory) - { - Remove-Item $testDirectory -Force -ea SilentlyContinue -Recurse - } - - # Create testDirectory, and destinationDirectory - New-Item $testDirectory -ItemType Directory -Force | Out-Null - New-Item $destinationDirectory -ItemType Directory -Force | Out-Null - } - - Context "Validate Copy-Item Locally." { - It "Copy-Item -Path $filePath -Destination $destinationFolderPath" { - - $filePath = CreateTestFile - $destinationFolderPath = GetDestinationFolderPath - Copy-Item -Path $filePath -Destination $destinationFolderPath - ValidateCopyItemOperation -filePath $filePath - } - - It "Copy-Item -Path $($testObject.SourceDirectory) -Destination $destinationFolderPath -Recurse" { - - $testObject = CreateTestDirectory - $destinationFolderPath = GetDestinationFolderPath - Copy-Item -Path $testObject.SourceDirectory -Destination $destinationFolderPath -Recurse - foreach ($file in $testObject.Files) - { - $copiedFilePath = ([string]$file).Replace("SourceDirectory", "DestinationDirectory\SourceDirectory") - $copiedFilePath | should Exist - } - } - } - - Context "Validate Copy-Item to remote session." { - - It "Copy one file to remote session." { - $filePath = CreateTestFile - $destinationFolderPath = GetDestinationFolderPath - Copy-Item -Path $filePath -ToSession $s -Destination $destinationFolderPath - ValidateCopyItemOperation -filePath $filePath - } - - It "Copy one read only file to remote session." { - - $filePath = CreateTestFile -setReadOnlyAttribute - $destinationFolderPath = GetDestinationFolderPath - Copy-Item -Path $filePath -ToSession $s -Destination $destinationFolderPath -Force - ValidateCopyItemOperation -filePath $filePath - } - - It "Copy-Item works for a read only file when '-Force' is not used." { - - $filePath = CreateTestFile -setReadOnlyAttribute - $destinationFolderPath = GetDestinationFolderPath - Copy-Item -Path $filePath -ToSession $s -Destination $destinationFolderPath -Verbose - ValidateCopyItemOperation -filePath $filePath - } - - It "Copy one folder to session Recursively" { - - $testObject = CreateTestDirectory - $destinationFolderPath = GetDestinationFolderPath - Copy-Item -Path $testObject.SourceDirectory -ToSession $s -Destination $destinationFolderPath -Recurse - - foreach ($file in $testObject.Files) - { - $copiedFilePath = ([string]$file).Replace("SourceDirectory", "DestinationDirectory\SourceDirectory") - $copiedFilePath | should Exist - (Get-Item $copiedFilePath).Length | should be (Get-Item $file).Length - } - } - - It "Copy folder with read only files to remote session recursively." { - $testObject = CreateTestDirectory -setReadOnlyAttribute - $destinationFolderPath = GetDestinationFolderPath - Copy-Item -Path $testObject.SourceDirectory -ToSession $s -Destination $destinationFolderPath -Recurse -Force - - foreach ($file in $testObject.Files) - { - $copiedFilePath = ([string]$file).Replace("SourceDirectory", "DestinationDirectory\SourceDirectory") - $copiedFilePath | should Exist - (Get-Item $copiedFilePath).Length | should be (Get-Item $file).Length - } - } - - It "Copy one file to remote session fails when the remote directory does not exist." { - - $filePath = CreateTestFile - $destinationFolderPath = GetDestinationFolderPath - $destinationFolderPath = Join-Path $destinationFolderPath "A\B\C\D\E" - $expectedFullyQualifiedErrorId = 'RemotePathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand' - - try - { - Copy-Item -Path $filePath -ToSession $s -Destination $destinationFolderPath -ErrorAction Stop - throw "CodeExecuted" - } - catch - { - $_.FullyQualifiedErrorId | should be $expectedFullyQualifiedErrorId - } - } - - It "Copy folder to remote session recursively works even if the target directory does not exist." { - $testObject = CreateTestDirectory -setReadOnlyAttribute - $destinationFolderPath = GetDestinationFolderPath - $destinationFolderPath = Join-Path $destinationFolderPath "FoderThatDoesNotExist" - Copy-Item -Path $testObject.SourceDirectory -ToSession $s -Destination $destinationFolderPath -Recurse -Force - - foreach ($file in $testObject.Files) - { - $copiedFilePath = ([string]$file).Replace("SourceDirectory", "DestinationDirectory\FoderThatDoesNotExist") - $copiedFilePath | should Exist - (Get-Item $copiedFilePath).Length | should be (Get-Item $file).Length - } - } - - It "Copy one empty file to remote session." { - - $filePath = CreateTestFile -emptyFile - $destinationFolderPath = GetDestinationFolderPath - $copiedFilePath = ([string]$filePath).Replace("SourceDirectory", "DestinationDirectory") - $copiedFilePath | should Not Exist - Copy-Item -Path $filePath -ToSession $s -Destination $destinationFolderPath - $copiedFilePath | should Exist - (Get-Item $copiedFilePath).Length | should be (Get-Item $filePath).Length - } - - It "Copy-Item to session supports alternate data streams." { - - $filePath = CreateTestFile - $destinationFolderPath = GetDestinationFolderPath - $streamContent = "This content is hidden" - $streamName = "Hidden" - Set-Content -Path $filePath -Value $streamContent -Stream $streamName - Copy-Item -Path $filePath -ToSession $s -Destination $destinationFolderPath -Verbose - ValidateCopyItemOperationForAlternateDataStream -filePath $filePath -streamName $streamName -expectedStreamContent $streamContent - } - } - - Context "Validate Copy-Item from remote session." { - - It "Copy one file from remote session." { - - $filePath = CreateTestFile - $destinationFolderPath = GetDestinationFolderPath - $copiedFilePath = ([string]$filePath).Replace("SourceDirectory", "DestinationDirectory") - $copiedFilePath | should Not Exist - Copy-Item -Path $filePath -FromSession $s -Destination $destinationFolderPath - ValidateCopyItemOperation -filePath $filePath - } - - It "Copy one empty file from remote session." { - - $filePath = CreateTestFile -emptyFile - $destinationFolderPath = GetDestinationFolderPath - $copiedFilePath = ([string]$filePath).Replace("SourceDirectory", "DestinationDirectory") - $copiedFilePath | should Not Exist - Copy-Item -Path $filePath -FromSession $s -Destination $destinationFolderPath - ValidateCopyItemOperation -filePath $filePath - } - - It "Copy folder from remote session recursively." { - - $testObject = CreateTestDirectory - $destinationFolderPath = GetDestinationFolderPath - $files = @(Get-ChildItem $destinationFolderPath -Recurse -Force) - Copy-Item -Path $testObject.SourceDirectory -FromSession $s -Destination $destinationFolderPath -Recurse - - foreach ($file in $testObject.Files) - { - $copiedFilePath = ([string]$file).Replace("SourceDirectory", "DestinationDirectory\SourceDirectory") - $copiedFilePath | should Exist - (Get-Item $copiedFilePath).Length | should be (Get-Item $file).Length - } - } - - It "Copy one file from remote session fails when the target directory does not exist." { - - $filePath = CreateTestFile - $destinationFolderPath = GetDestinationFolderPath - $destinationFolderPath = Join-Path $destinationFolderPath "A\B\C\D\E" - $expectedFullyQualifiedErrorId = 'CopyItemRemotelyIOError,Microsoft.PowerShell.Commands.CopyItemCommand' - try - { - Copy-Item -Path $filePath -FromSession $s -Destination $destinationFolderPath -ErrorAction Stop - throw "CodeExecuted" - } - catch - { - $_.FullyQualifiedErrorId | should be $expectedFullyQualifiedErrorId - } - } - - It "Copy folder from remote session recursively works even if the target directory does not exist." { - - $testObject = CreateTestDirectory - $destinationFolderPath = GetDestinationFolderPath - $destinationFolderPath = Join-Path $destinationFolderPath "FoderThatDoesNotExist" - $files = @(Get-ChildItem $destinationFolderPath -Recurse -Force) - Copy-Item -Path $testObject.SourceDirectory -FromSession $s -Destination $destinationFolderPath -Recurse - - foreach ($file in $testObject.Files) - { - $copiedFilePath = ([string]$file).Replace("SourceDirectory", "DestinationDirectory\FoderThatDoesNotExist") - $copiedFilePath | should Exist - (Get-Item $copiedFilePath).Length | should be (Get-Item $file).Length - } - } - - It "Copy a read only file from a remote session." { - - $filePath = CreateTestFile -setReadOnlyAttribute - $destinationFolderPath = GetDestinationFolderPath - $copiedFilePath = ([string]$filePath).Replace("SourceDirectory", "DestinationDirectory") - Copy-Item -Path $filePath -FromSession $s -Destination $destinationFolderPath -Force - ValidateCopyItemOperation -filePath $filePath - } - - It "Copy-Item for a read only file works with no '-force' parameter." { - - $filePath = CreateTestFile -setReadOnlyAttribute - $destinationFolderPath = GetDestinationFolderPath - Copy-Item -Path $filePath -FromSession $s -Destination $destinationFolderPath - ValidateCopyItemOperation -filePath $filePath - } - - It "Copy-Item -FromSession works even when trying to copy an assembly that is currently being used by another process." { - - $testAssembly = GenerateTestAssembly - $destinationFolderPath = GetDestinationFolderPath - Import-Module $testAssembly.Path -Force - try - { - Copy-Item -Path $testAssembly.Path -FromSession $s -Destination $destinationFolderPath - ValidateCopyItemOperation -filePath $testAssembly.Path - } - finally - { - Remove-Module $testAssembly.ModuleName -Force -ea SilentlyContinue - } - } - - It "Copy-Item from session supports alternate data streams." { - - $filePath = CreateTestFile - $destinationFolderPath = GetDestinationFolderPath - $streamContent = "This content is hidden" - $streamName = "Hidden" - Set-Content -Path $filePath -Value $streamContent -Stream $streamName - Copy-Item -Path $filePath -FromSession $s -Destination $destinationFolderPath - ValidateCopyItemOperationForAlternateDataStream -filePath $filePath -streamName $streamName -expectedStreamContent $streamContent - } - } - - Context "Validate Copy-Item Remotely using wildcards" { - - It "Copy-Item from session using wildcards." { - - $testObject = CreateTestDirectory - $destinationFolderPath = GetDestinationFolderPath - $sourcePathWithWildcards = "$($testObject.SourceDirectory)\A\*.txt" - Copy-Item -Path $sourcePathWithWildcards -FromSession $s -Destination $destinationFolderPath -Force - - $sourceFiles = @(Get-Item $sourcePathWithWildcards) - foreach ($file in $sourceFiles) - { - $copiedFilePath = Join-Path $destinationFolderPath (Split-Path $file -Leaf) - $copiedFilePath | Should Exist - (Get-Item $copiedFilePath).Length | Should Be (Get-Item $file).Length - } - } - - It "Copy-Item to session using wildcards." { - - $testObject = CreateTestDirectory - $destinationFolderPath = GetDestinationFolderPath - $sourcePathWithWildcards = "$($testObject.SourceDirectory)\A\*.txt" - Copy-Item -Path $sourcePathWithWildcards -ToSession $s -Destination $destinationFolderPath -Force - - $sourceFiles = @(Get-Item $sourcePathWithWildcards) - foreach ($file in $sourceFiles) - { - $copiedFilePath = Join-Path $destinationFolderPath (Split-Path $file -Leaf) - $copiedFilePath | Should Exist - (Get-Item $copiedFilePath).Length | Should Be (Get-Item $file).Length - } - } - } - - Context "Validate FullyQualifiedErrorIds for remote source and destination paths." { - - BeforeAll { - # Create test file. - $testFilePath = Join-Path "TestDrive:" "testfile.txt" - if (test-path $testFilePath) - { - Remove-Item $testFilePath -Force -ea SilentlyContinue - } - "File test content" | Out-File $testFilePath -Force - } - - function Test-CopyItemError - { - param ($path, $destination, $expectedFullyQualifiedErrorId, $fromSession = $false) - - if ($fromSession) - { - It "Copy-Item FromSession -Path '$path' throws $expectedFullyQualifiedErrorId" { - try - { - Copy-Item -Path $path -FromSession $s -Destination $destination -ErrorAction Stop - throw "CodeExecuted" - } - catch - { - $_.FullyQualifiedErrorId | should be $expectedFullyQualifiedErrorId - } - } - } - else - { - It "Copy-Item ToSession -Destination '$path' throws $expectedFullyQualifiedErrorId" { - try - { - Copy-Item -Path $path -ToSession $s -Destination $destination -ErrorAction Stop - throw "CodeExecuted" - } - catch - { - $_.FullyQualifiedErrorId | should be $expectedFullyQualifiedErrorId - } - } - } - } - - $invalidSourcePathtestCases = @( - @{ - Path = "HKLM:\SOFTWARE" - Destination = $env:SystemDrive - ExpectedFullyQualifiedErrorId = "NamedParameterNotFound,Microsoft.PowerShell.Commands.CopyItemCommand" - FromSession = $true - } - @{ - Path = ".\Source" - Destination = $env:SystemDrive - ExpectedFullyQualifiedErrorId = "RemotePathIsNotAbsolute,Microsoft.PowerShell.Commands.CopyItemCommand" - FromSession = $true - } - @{ - Path = $env:SystemDrive + "\X\Y\Z" - Destination = $env:SystemDrive + "\A\B\C" - ExpectedFullyQualifiedErrorId = "RemotePathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand" - FromSession = $true - } - @{ - Path = $null - Destination = $env:SystemDrive - ExpectedFullyQualifiedErrorId = "ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.CopyItemCommand" - FromSession = $true - } - @{ - Path = '' - Destination = $env:SystemDrive - ExpectedFullyQualifiedErrorId = "ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.CopyItemCommand" - FromSession = $true - } - @{ - Path = "$env:SystemDrive\nonexistdir\*" - Destination = "$env:SystemDrive\psTest" - ExpectedFullyQualifiedErrorId = "RemotePathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand" - FromSession = $true - } - ) - - foreach ($testCase in $invalidSourcePathtestCases) { - Test-CopyItemError @testCase - } - - $invalidDestinationPathtestCases = @( - @{ - Path = $testFilePath - Destination = ".\Source" - ExpectedFullyQualifiedErrorId = "RemotePathIsNotAbsolute,Microsoft.PowerShell.Commands.CopyItemCommand" - } - @{ - Path = $testFilePath - Destination = $env:SystemDrive + "\X\A\B\C" - ExpectedFullyQualifiedErrorId = "RemotePathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand" - } - @{ - Path = $testFilePath - Destination = $null - ExpectedFullyQualifiedErrorId = "CopyItemRemoteDestinationIsNullOrEmpty,Microsoft.PowerShell.Commands.CopyItemCommand" - } - @{ - Path = $testFilePath - Destination = "" - ExpectedFullyQualifiedErrorId = "CopyItemRemoteDestinationIsNullOrEmpty,Microsoft.PowerShell.Commands.CopyItemCommand" - } - @{ - Path = "$env:SystemDrive\nonexistdir\*" - Destination = "$env:SystemDrive\psTest" - ExpectedFullyQualifiedErrorId = "PathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand" - } - ) - - foreach ($testCase in $invalidDestinationPathtestCases) { - Test-CopyItemError @testCase - } - } -} - -Describe "Validate Copy-Item error for target sessions not in FullLanguageMode." -Tags "Feature" { - - BeforeAll { - - $testDirectory = "TestDrive:\" - - # Create the test file and directories. - $source = "$testDirectory\Source" - $destination = "$testDirectory\Destination" - - New-Item $source -ItemType Directory -Force | Out-Null - New-Item $destination -ItemType Directory -Force | Out-Null - - $testFilePath = Join-Path $source "testfile.txt" - "File test content" | Out-File $testFilePath -Force - - # Keep track of the sessions. - $testSessions = @{} - - # Keep track of the session names to be unregistered. - $sessionToUnregister = @() - - $languageModes = @("ConstrainedLanguage", "NoLanguage", "RestrictedLanguage") - $id = (Get-Random).ToString() - - foreach ($languageMode in $languageModes) - { - $sessionName = $languageMode + "_" + $id - $sessionToUnregister += $sessionName - $configFilePath = Join-Path $testDirectory "test.pssc" - - # Create the session. - Write-Host "Creating pssession with '$languageMode' ..." - New-PSSessionConfigurationFile -Path $configFilePath -SessionType Default -LanguageMode $languageMode - Register-PSSessionConfiguration -Name $sessionName -Path $configFilePath -Force | Out-Null - $testSession = New-PSSession -ConfigurationName $sessionName - - # Validate that the session is opened. - $testSession.State | Should Be "Opened" - - # Add the new session to the list. - $testSessions[$languageMode] = $testSession - - # Remove the pssc file. - Remove-Item $configFilePath -Force -ea SilentlyContinue - } - } - - AfterAll { - - $testSessions.Values | Remove-PSSession -ea SilentlyContinue - - $sessionToUnregister | foreach { - Unregister-PSSessionConfiguration -Name $_ -Force -ea SilentlyContinue - } - } - - foreach ($languageMode in $testSessions.Keys) - { - $session = $testSessions[$languageMode] - - It "Copy-Item throws 'SessionIsNotInFullLanguageMode' error for a session in '$languageMode'" { - - # FromSession - try - { - Copy-Item -Path $testFilePath -FromSession $session -Destination $destination -Force -Verbose -ea Stop - throw "CodeExecuted" - } - catch - { - $_.FullyQualifiedErrorId | should be "SessionIsNotInFullLanguageMode,Microsoft.PowerShell.Commands.CopyItemCommand" - } - - # ToSession - try - { - Copy-Item -Path $testFilePath -ToSession $session -Destination $destination -Force -Verbose -ea Stop - throw "CodeExecuted" - } - catch - { - $_.FullyQualifiedErrorId | should be "SessionIsNotInFullLanguageMode,Microsoft.PowerShell.Commands.CopyItemCommand" - } - } - } -} - -Describe "Copy-Item can use Recurse and Exclude together" -Tags "Feature" { - - Context "Local and Remote Tests" { - - BeforeAll { - $s = New-PSSession -ComputerName . -ea SilentlyContinue - if (-not $s) - { - throw "Failed to create PSSession for remote copy operations." - } - - $null = New-Item -ItemType Directory -Path "TestDrive:\Parent\Sub" - $null = New-Item -Path "TestDrive:\Parent\p1.txt" -Value "test" - $null = New-Item -Path "TestDrive:\Parent\p2.txt" -Value "test" - $null = New-Item -Path "TestDrive:\Parent\s4.txt" -Value "test" - $null = New-Item -Path "TestDrive:\Parent\Sub\s1.txt" -Value "test" - $null = New-Item -Path "TestDrive:\Parent\Sub\s2.txt" -Value "test" - $null = New-Item -Path "TestDrive:\Parent\Sub\s3.txt" -Value "test" - $null = New-Item -Path "TestDrive:\Parent\Sub\p3.txt" -Value "testcl" - } - - It "can exclude files at sub directory" { - Copy-Item -Path TestDrive:\Parent\* -Recurse -Exclude s*.txt -Destination TestDrive:\Temp -Force - $copiedFiles = Get-ChildItem -Recurse -Path TestDrive:\Temp - $copiedFiles.Count | Should Be 3 - } - - It "can exclude files at sub directory to a session" { - Copy-Item -Path TestDrive:\Parent\* -Recurse -Exclude s*.txt -Destination $TestDrive\Temp2 -Force -ToSession $s - $copiedFiles = Get-ChildItem -Recurse -Path TestDrive:\Temp - $copiedFiles.Count | Should Be 3 - } - - It "can exclude files at sub directory from a session" { - Copy-Item -Path $TestDrive\Parent\* -Recurse -Exclude s*.txt -Destination TestDrive:\Temp3 -FromSession $s - $copiedFiles = Get-ChildItem -Recurse -Path TestDrive:\Temp2 - $copiedFiles.Count | Should Be 3 - } - - AfterAll { - Remove-PSSession -Session $s -ErrorAction SilentlyContinue - } - } -} - -Describe "Copy-Item remotely bug fixes" -Tags "Feature" { - - BeforeAll { - $s = New-PSSession -ComputerName . -ErrorAction SilentlyContinue - if (-not $s) - { - throw "Failed to create PSSession for remote copy operations." - } - - $originalContent = "test file 1 - Source" - $newContent = "This is some new content" - - $null = New-Item -ItemType Directory -Path "TestDrive:\Source" - $null = New-Item -ItemType Directory -Path "TestDrive:\Destination" - } - - AfterAll { - Remove-PSSession -Session $s -ErrorAction SilentlyContinue - } - - BeforeEach { - - # Create the same file in the source and destination - Set-Content -Path "TestDrive:\Source\testFile1.txt" -Value $originalContent -Force - Set-Content -Path "TestDrive:\Destination\testFile1.txt" -Value $originalContent -Force - } - - Context "Copy-Item remotely overwrites a destination file if it exists." { - - BeforeEach { - - # Overwrite the source file - Set-Content -Path "TestDrive:\Source\testFile1.txt" -Value $newContent - } - - It "Copy item -tosession overwrites the content of an existing file." { - - # Copy file to session - Copy-Item -Path "TestDrive:\Source\testFile1.txt" -Destination "$TestDrive\Destination\testFile1.txt" -ToSession $s - - # Validate the the file was overwritten - $fileContent = Get-Content "TestDrive:\Destination\testFile1.txt" -ea SilentlyContinue -Raw - $fileContent | Should Match $newContent - } - - It "Copy item -fromsession overwrites the content of an existing file." { - - # Copy file to session - Copy-Item -Path "$TestDrive\Source\testFile1.txt" -Destination "TestDrive:\Destination\testFile1.txt" -FromSession $s - - # Validate the the file was overwritten - $fileContent = Get-Content "TestDrive:\Destination\testFile1.txt" -ea SilentlyContinue -Raw - $fileContent | Should Match $newContent - } - } - - Context "Copy-Item remotely creates a destination file if it does not exist." { - - BeforeEach { - - if (Test-Path "TestDrive:\AnotherDestination") - { - Remove-Item "TestDrive:\AnotherDestination" -Force -Recurse -ea SilentlyContinue - } - $null = New-Item -ItemType Directory -Path "TestDrive:\AnotherDestination" - - # Ensure the file does not exist - "TestDrive:\AnotherDestination\FileThatDoesNotExist.txt" | Should Not Exist - } - - It "Copy-Item -tosession creates the file if it does not exist on the remote destination." { - - # Copy file to session - Copy-Item -Path "TestDrive:\Source\testFile1.txt" -Destination "$TestDrive\AnotherDestination\FileThatDoesNotExist.txt" -ToSession $s - - # Verify that the file was created - "TestDrive:\AnotherDestination\FileThatDoesNotExist.txt" | Should Exist - } - - It "Copy-Item -fromsession creates the file if it does not exist on the local machine." { - - # Copy file from session - Copy-Item -Path "$TestDrive\Source\testFile1.txt" -Destination "TestDrive:\AnotherDestination\FileThatDoesNotExist.txt" -FromSession $s - - # Verify that the file was created - "TestDrive:\AnotherDestination\FileThatDoesNotExist.txt" | Should Exist - } - } -} +# This is a Pester test suite to validate Copy-Item remotely using a remote session. +# +# Copyright (c) Microsoft Corporation, 2015 +# +# + +# If PS Remoting is not available, do not run the suite. +function ShouldRun +{ + if ( $IsCore ) { return $false } + $result = Invoke-Command -ComputerName . -ScriptBlock {1} -ErrorAction SilentlyContinue + return ($result -eq 1) +} + +if (-not (ShouldRun)) +{ + Write-Host "PS Remoting is not available, skipping tests..." -ForegroundColor Cyan + return +} + +Describe "Validate Copy-Item Remotely" -Tags "CI" { + + # Validate a copy item operation. + # $filePath is the source file path + # + function ValidateCopyItemOperation + { + param ([string]$filePath, [string]$destination) + + if (-not $destination) + { + $copiedFilePath = ([string]$filePath).Replace("SourceDirectory", "DestinationDirectory") + } + else + { + $fileName = Split-Path $filePath -Leaf + $copiedFilePath = Join-Path $destination $fileName + } + + $copiedFilePath | should Exist + + # Validate file attributes + $originalFile = Get-Item $filePath -Force + $newFile = Get-Item $copiedFilePath -Force + + # Validate file Length + $newFile.Length | should be $originalFile.Length + + # Validate LastWriteTime + $newFile.LastWriteTime | should be $originalFile.LastWriteTime + $newFile.LastWriteTimeUtc | should be $originalFile.LastWriteTimeUtc + + # Validate Attributes + $newFile.Attributes.value__ | Should Be $originalFile.Attributes.value__ + } + + # Validate a copy item operation. + # $filePath is the source file path + # + function ValidateCopyItemOperationForAlternateDataStream + { + param ([string]$filePath, $streamName, $expectedStreamContent) + + $copiedFilePath = ([string]$filePath).Replace("SourceDirectory", "DestinationDirectory") + $copiedFilePath | should Exist + (Get-Item $copiedFilePath).Length | should be (Get-Item $filePath).Length + + # Validate the stream + $actualStreamContent = Get-Content -Path $copiedFilePath -Stream $streamName -ea SilentlyContinue + $actualStreamContent | Should Match $expectedStreamContent + } + + BeforeAll { + $s = New-PSSession -ComputerName . -ea SilentlyContinue + if (-not $s) + { + throw "Failed to create PSSession for remote copy operations." + } + + $destinationFolderName = "DestinationDirectory" + $sourceFolderName = "SourceDirectory" + $testDirectory = Join-Path "TestDrive:" "copyItemRemotely" + $destinationDirectory = Join-Path $testDirectory $destinationFolderName + $sourceDirectory = Join-Path $testDirectory $sourceFolderName + + # Creates one txt file + # + function CreateTestFile + { + param ([switch]$setReadOnlyAttribute = $false, [switch]$emptyFile = $false) + + # Create the test directory. + New-Item -Path $sourceDirectory -Force -ItemType Directory | Out-Null + + # Create the file. + $filePath = Join-Path $sourceDirectory "testfileone.txt" + if (-not $emptyFile) + { + "File test content" | Out-File $filePath -Force + } + else + { + "" | Out-File $filePath -Force + } + + if (-not (Test-Path $filePath)) + { + throw "Failed to create test file $filePath." + } + + if ($setReadOnlyAttribute) + { + Set-ItemProperty $filePath -Name IsReadOnly -value $true -Force + } + + return (Get-Item $filePath).FullName + } + + # Create a set of directories and files with the following structure: + # .\copyItemRemotely\SourceDirectory\A\a.txt + # .\copyItemRemotely\SourceDirectory\A\a2.txt + # .\copyItemRemotely\SourceDirectory\rootFile.txt + # .\copyItemRemotely\SourceDirectory\B\b.txt + # .\copyItemRemotely\SourceDirectory\C\D\d.txt + # + function CreateTestDirectory + { + param ([switch]$setReadOnlyAttribute = $false) + + $directoriesToCreate = @() + $directoriesToCreate += "A" + $directoriesToCreate += "B" + $directoriesToCreate += "C\D" + + $filesToCreate = @() + $filesToCreate += "rootFile.txt" + $filesToCreate += "A\a.txt" + $filesToCreate += "A\a2.txt" + $filesToCreate += "B\b.txt" + $filesToCreate += "C\D\d.txt" + + # Create the directories. + foreach ($directory in $directoriesToCreate) + { + $directoryPath = Join-Path $sourceDirectory $directory + New-Item -Path $directoryPath -Force -ItemType Directory | Out-Null + } + + $result = @{ + SourceDirectory = (Get-Item $sourceDirectory).FullName + Files = @() + } + + # Create the files. + foreach ($file in $filesToCreate) + { + $filePath = Join-Path $sourceDirectory $file + $file + "`r`n File test content" | Out-File $filePath -Force + + if (-not (Test-Path $filePath)) + { + throw "Failed to create test file $filePath." + } + + if ($setReadOnlyAttribute) + { + Set-ItemProperty $filePath -Name IsReadOnly -value $true -Force + } + + $result.Files += (Get-Item $filePath).FullName + } + + return $result + } + + function GenerateTestAssembly + { + $assemblyPath = Join-Path $env:TEMP TestModule + $outputPath = Join-Path $assemblyPath TestModule.dll + + if (-not (Test-Path $assemblyPath)) + { + New-Item $assemblyPath -Force -ItemType Directory | Out-Null + } + + if (-not (Test-Path $outputPath)) + { + $code = @" + namespace TestModule + { + using System; + using System.Management.Automation; + + [Cmdlet(VerbsCommon.Get, "TestModule")] + public class TestSameCmdlets : PSCmdlet + { + protected override void ProcessRecord() + { + WriteObject("TestModule"); + } + } + } +"@ + Add-Type -TypeDefinition $code -OutputAssembly $outputPath + } + + $result = @{ + ModuleName = "TestModule" + Path = (Get-Item $outputPath).FullName + } + + return $result + } + + function GetDestinationFolderPath + { + return (Get-Item $destinationDirectory).FullName + } + } + + AfterAll { + Remove-PSSession -Name $s.Name -ea SilentlyContinue + } + + BeforeEach { + <# Ensure we start with an empty test directory. Here is the file structure + + $destinationFolderName = "DestinationDirectory" + $sourceFolderName = "SourceDirectory" + $testDirectory = Join-Path "TestDrive:" "copyItemRemotely" + $destinationDirectory = Join-Path $testDirectory $destinationFolderName + $sourceDirectory = Join-Path $testDirectory $sourceFolderName + #> + + if (test-path $testDirectory) + { + Remove-Item $testDirectory -Force -ea SilentlyContinue -Recurse + } + + # Create testDirectory, and destinationDirectory + New-Item $testDirectory -ItemType Directory -Force | Out-Null + New-Item $destinationDirectory -ItemType Directory -Force | Out-Null + } + + Context "Validate Copy-Item Locally." { + It "Copy-Item -Path $filePath -Destination $destinationFolderPath" { + + $filePath = CreateTestFile + $destinationFolderPath = GetDestinationFolderPath + Copy-Item -Path $filePath -Destination $destinationFolderPath + ValidateCopyItemOperation -filePath $filePath + } + + It "Copy-Item -Path $($testObject.SourceDirectory) -Destination $destinationFolderPath -Recurse" { + + $testObject = CreateTestDirectory + $destinationFolderPath = GetDestinationFolderPath + Copy-Item -Path $testObject.SourceDirectory -Destination $destinationFolderPath -Recurse + foreach ($file in $testObject.Files) + { + $copiedFilePath = ([string]$file).Replace("SourceDirectory", "DestinationDirectory\SourceDirectory") + $copiedFilePath | should Exist + } + } + } + + Context "Validate Copy-Item to remote session." { + + It "Copy one file to remote session." { + $filePath = CreateTestFile + $destinationFolderPath = GetDestinationFolderPath + Copy-Item -Path $filePath -ToSession $s -Destination $destinationFolderPath + ValidateCopyItemOperation -filePath $filePath + } + + It "Copy one read only file to remote session." { + + $filePath = CreateTestFile -setReadOnlyAttribute + $destinationFolderPath = GetDestinationFolderPath + Copy-Item -Path $filePath -ToSession $s -Destination $destinationFolderPath -Force + ValidateCopyItemOperation -filePath $filePath + } + + It "Copy-Item works for a read only file when '-Force' is not used." { + + $filePath = CreateTestFile -setReadOnlyAttribute + $destinationFolderPath = GetDestinationFolderPath + Copy-Item -Path $filePath -ToSession $s -Destination $destinationFolderPath -Verbose + ValidateCopyItemOperation -filePath $filePath + } + + It "Copy one folder to session Recursively" { + + $testObject = CreateTestDirectory + $destinationFolderPath = GetDestinationFolderPath + Copy-Item -Path $testObject.SourceDirectory -ToSession $s -Destination $destinationFolderPath -Recurse + + foreach ($file in $testObject.Files) + { + $copiedFilePath = ([string]$file).Replace("SourceDirectory", "DestinationDirectory\SourceDirectory") + $copiedFilePath | should Exist + (Get-Item $copiedFilePath).Length | should be (Get-Item $file).Length + } + } + + It "Copy folder with read only files to remote session recursively." { + $testObject = CreateTestDirectory -setReadOnlyAttribute + $destinationFolderPath = GetDestinationFolderPath + Copy-Item -Path $testObject.SourceDirectory -ToSession $s -Destination $destinationFolderPath -Recurse -Force + + foreach ($file in $testObject.Files) + { + $copiedFilePath = ([string]$file).Replace("SourceDirectory", "DestinationDirectory\SourceDirectory") + $copiedFilePath | should Exist + (Get-Item $copiedFilePath).Length | should be (Get-Item $file).Length + } + } + + It "Copy one file to remote session fails when the remote directory does not exist." { + + $filePath = CreateTestFile + $destinationFolderPath = GetDestinationFolderPath + $destinationFolderPath = Join-Path $destinationFolderPath "A\B\C\D\E" + $expectedFullyQualifiedErrorId = 'RemotePathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand' + + try + { + Copy-Item -Path $filePath -ToSession $s -Destination $destinationFolderPath -ErrorAction Stop + throw "CodeExecuted" + } + catch + { + $_.FullyQualifiedErrorId | should be $expectedFullyQualifiedErrorId + } + } + + It "Copy folder to remote session recursively works even if the target directory does not exist." { + $testObject = CreateTestDirectory -setReadOnlyAttribute + $destinationFolderPath = GetDestinationFolderPath + $destinationFolderPath = Join-Path $destinationFolderPath "FoderThatDoesNotExist" + Copy-Item -Path $testObject.SourceDirectory -ToSession $s -Destination $destinationFolderPath -Recurse -Force + + foreach ($file in $testObject.Files) + { + $copiedFilePath = ([string]$file).Replace("SourceDirectory", "DestinationDirectory\FoderThatDoesNotExist") + $copiedFilePath | should Exist + (Get-Item $copiedFilePath).Length | should be (Get-Item $file).Length + } + } + + It "Copy one empty file to remote session." { + + $filePath = CreateTestFile -emptyFile + $destinationFolderPath = GetDestinationFolderPath + $copiedFilePath = ([string]$filePath).Replace("SourceDirectory", "DestinationDirectory") + $copiedFilePath | should Not Exist + Copy-Item -Path $filePath -ToSession $s -Destination $destinationFolderPath + $copiedFilePath | should Exist + (Get-Item $copiedFilePath).Length | should be (Get-Item $filePath).Length + } + + It "Copy-Item to session supports alternate data streams." { + + $filePath = CreateTestFile + $destinationFolderPath = GetDestinationFolderPath + $streamContent = "This content is hidden" + $streamName = "Hidden" + Set-Content -Path $filePath -Value $streamContent -Stream $streamName + Copy-Item -Path $filePath -ToSession $s -Destination $destinationFolderPath -Verbose + ValidateCopyItemOperationForAlternateDataStream -filePath $filePath -streamName $streamName -expectedStreamContent $streamContent + } + } + + Context "Validate Copy-Item from remote session." { + + It "Copy one file from remote session." { + + $filePath = CreateTestFile + $destinationFolderPath = GetDestinationFolderPath + $copiedFilePath = ([string]$filePath).Replace("SourceDirectory", "DestinationDirectory") + $copiedFilePath | should Not Exist + Copy-Item -Path $filePath -FromSession $s -Destination $destinationFolderPath + ValidateCopyItemOperation -filePath $filePath + } + + It "Copy one empty file from remote session." { + + $filePath = CreateTestFile -emptyFile + $destinationFolderPath = GetDestinationFolderPath + $copiedFilePath = ([string]$filePath).Replace("SourceDirectory", "DestinationDirectory") + $copiedFilePath | should Not Exist + Copy-Item -Path $filePath -FromSession $s -Destination $destinationFolderPath + ValidateCopyItemOperation -filePath $filePath + } + + It "Copy folder from remote session recursively." { + + $testObject = CreateTestDirectory + $destinationFolderPath = GetDestinationFolderPath + $files = @(Get-ChildItem $destinationFolderPath -Recurse -Force) + Copy-Item -Path $testObject.SourceDirectory -FromSession $s -Destination $destinationFolderPath -Recurse + + foreach ($file in $testObject.Files) + { + $copiedFilePath = ([string]$file).Replace("SourceDirectory", "DestinationDirectory\SourceDirectory") + $copiedFilePath | should Exist + (Get-Item $copiedFilePath).Length | should be (Get-Item $file).Length + } + } + + It "Copy one file from remote session fails when the target directory does not exist." { + + $filePath = CreateTestFile + $destinationFolderPath = GetDestinationFolderPath + $destinationFolderPath = Join-Path $destinationFolderPath "A\B\C\D\E" + $expectedFullyQualifiedErrorId = 'CopyItemRemotelyIOError,Microsoft.PowerShell.Commands.CopyItemCommand' + try + { + Copy-Item -Path $filePath -FromSession $s -Destination $destinationFolderPath -ErrorAction Stop + throw "CodeExecuted" + } + catch + { + $_.FullyQualifiedErrorId | should be $expectedFullyQualifiedErrorId + } + } + + It "Copy folder from remote session recursively works even if the target directory does not exist." { + + $testObject = CreateTestDirectory + $destinationFolderPath = GetDestinationFolderPath + $destinationFolderPath = Join-Path $destinationFolderPath "FoderThatDoesNotExist" + $files = @(Get-ChildItem $destinationFolderPath -Recurse -Force) + Copy-Item -Path $testObject.SourceDirectory -FromSession $s -Destination $destinationFolderPath -Recurse + + foreach ($file in $testObject.Files) + { + $copiedFilePath = ([string]$file).Replace("SourceDirectory", "DestinationDirectory\FoderThatDoesNotExist") + $copiedFilePath | should Exist + (Get-Item $copiedFilePath).Length | should be (Get-Item $file).Length + } + } + + It "Copy a read only file from a remote session." { + + $filePath = CreateTestFile -setReadOnlyAttribute + $destinationFolderPath = GetDestinationFolderPath + $copiedFilePath = ([string]$filePath).Replace("SourceDirectory", "DestinationDirectory") + Copy-Item -Path $filePath -FromSession $s -Destination $destinationFolderPath -Force + ValidateCopyItemOperation -filePath $filePath + } + + It "Copy-Item for a read only file works with no '-force' parameter." { + + $filePath = CreateTestFile -setReadOnlyAttribute + $destinationFolderPath = GetDestinationFolderPath + Copy-Item -Path $filePath -FromSession $s -Destination $destinationFolderPath + ValidateCopyItemOperation -filePath $filePath + } + + It "Copy-Item -FromSession works even when trying to copy an assembly that is currently being used by another process." { + + $testAssembly = GenerateTestAssembly + $destinationFolderPath = GetDestinationFolderPath + Import-Module $testAssembly.Path -Force + try + { + Copy-Item -Path $testAssembly.Path -FromSession $s -Destination $destinationFolderPath + ValidateCopyItemOperation -filePath $testAssembly.Path + } + finally + { + Remove-Module $testAssembly.ModuleName -Force -ea SilentlyContinue + } + } + + It "Copy-Item from session supports alternate data streams." { + + $filePath = CreateTestFile + $destinationFolderPath = GetDestinationFolderPath + $streamContent = "This content is hidden" + $streamName = "Hidden" + Set-Content -Path $filePath -Value $streamContent -Stream $streamName + Copy-Item -Path $filePath -FromSession $s -Destination $destinationFolderPath + ValidateCopyItemOperationForAlternateDataStream -filePath $filePath -streamName $streamName -expectedStreamContent $streamContent + } + } + + Context "Validate Copy-Item Remotely using wildcards" { + + It "Copy-Item from session using wildcards." { + + $testObject = CreateTestDirectory + $destinationFolderPath = GetDestinationFolderPath + $sourcePathWithWildcards = "$($testObject.SourceDirectory)\A\*.txt" + Copy-Item -Path $sourcePathWithWildcards -FromSession $s -Destination $destinationFolderPath -Force + + $sourceFiles = @(Get-Item $sourcePathWithWildcards) + foreach ($file in $sourceFiles) + { + $copiedFilePath = Join-Path $destinationFolderPath (Split-Path $file -Leaf) + $copiedFilePath | Should Exist + (Get-Item $copiedFilePath).Length | Should Be (Get-Item $file).Length + } + } + + It "Copy-Item to session using wildcards." { + + $testObject = CreateTestDirectory + $destinationFolderPath = GetDestinationFolderPath + $sourcePathWithWildcards = "$($testObject.SourceDirectory)\A\*.txt" + Copy-Item -Path $sourcePathWithWildcards -ToSession $s -Destination $destinationFolderPath -Force + + $sourceFiles = @(Get-Item $sourcePathWithWildcards) + foreach ($file in $sourceFiles) + { + $copiedFilePath = Join-Path $destinationFolderPath (Split-Path $file -Leaf) + $copiedFilePath | Should Exist + (Get-Item $copiedFilePath).Length | Should Be (Get-Item $file).Length + } + } + } + + Context "Validate FullyQualifiedErrorIds for remote source and destination paths." { + + BeforeAll { + # Create test file. + $testFilePath = Join-Path "TestDrive:" "testfile.txt" + if (test-path $testFilePath) + { + Remove-Item $testFilePath -Force -ea SilentlyContinue + } + "File test content" | Out-File $testFilePath -Force + } + + function Test-CopyItemError + { + param ($path, $destination, $expectedFullyQualifiedErrorId, $fromSession = $false) + + if ($fromSession) + { + It "Copy-Item FromSession -Path '$path' throws $expectedFullyQualifiedErrorId" { + try + { + Copy-Item -Path $path -FromSession $s -Destination $destination -ErrorAction Stop + throw "CodeExecuted" + } + catch + { + $_.FullyQualifiedErrorId | should be $expectedFullyQualifiedErrorId + } + } + } + else + { + It "Copy-Item ToSession -Destination '$path' throws $expectedFullyQualifiedErrorId" { + try + { + Copy-Item -Path $path -ToSession $s -Destination $destination -ErrorAction Stop + throw "CodeExecuted" + } + catch + { + $_.FullyQualifiedErrorId | should be $expectedFullyQualifiedErrorId + } + } + } + } + + $invalidSourcePathtestCases = @( + @{ + Path = "HKLM:\SOFTWARE" + Destination = $env:SystemDrive + ExpectedFullyQualifiedErrorId = "NamedParameterNotFound,Microsoft.PowerShell.Commands.CopyItemCommand" + FromSession = $true + } + @{ + Path = ".\Source" + Destination = $env:SystemDrive + ExpectedFullyQualifiedErrorId = "RemotePathIsNotAbsolute,Microsoft.PowerShell.Commands.CopyItemCommand" + FromSession = $true + } + @{ + Path = $env:SystemDrive + "\X\Y\Z" + Destination = $env:SystemDrive + "\A\B\C" + ExpectedFullyQualifiedErrorId = "RemotePathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand" + FromSession = $true + } + @{ + Path = $null + Destination = $env:SystemDrive + ExpectedFullyQualifiedErrorId = "ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.CopyItemCommand" + FromSession = $true + } + @{ + Path = '' + Destination = $env:SystemDrive + ExpectedFullyQualifiedErrorId = "ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.CopyItemCommand" + FromSession = $true + } + @{ + Path = "$env:SystemDrive\nonexistdir\*" + Destination = "$env:SystemDrive\psTest" + ExpectedFullyQualifiedErrorId = "RemotePathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand" + FromSession = $true + } + ) + + foreach ($testCase in $invalidSourcePathtestCases) { + Test-CopyItemError @testCase + } + + $invalidDestinationPathtestCases = @( + @{ + Path = $testFilePath + Destination = ".\Source" + ExpectedFullyQualifiedErrorId = "RemotePathIsNotAbsolute,Microsoft.PowerShell.Commands.CopyItemCommand" + } + @{ + Path = $testFilePath + Destination = $env:SystemDrive + "\X\A\B\C" + ExpectedFullyQualifiedErrorId = "RemotePathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand" + } + @{ + Path = $testFilePath + Destination = $null + ExpectedFullyQualifiedErrorId = "CopyItemRemoteDestinationIsNullOrEmpty,Microsoft.PowerShell.Commands.CopyItemCommand" + } + @{ + Path = $testFilePath + Destination = "" + ExpectedFullyQualifiedErrorId = "CopyItemRemoteDestinationIsNullOrEmpty,Microsoft.PowerShell.Commands.CopyItemCommand" + } + @{ + Path = "$env:SystemDrive\nonexistdir\*" + Destination = "$env:SystemDrive\psTest" + ExpectedFullyQualifiedErrorId = "PathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand" + } + ) + + foreach ($testCase in $invalidDestinationPathtestCases) { + Test-CopyItemError @testCase + } + } +} + +Describe "Validate Copy-Item error for target sessions not in FullLanguageMode." -Tags "Feature" { + + BeforeAll { + + $testDirectory = "TestDrive:\" + + # Create the test file and directories. + $source = "$testDirectory\Source" + $destination = "$testDirectory\Destination" + + New-Item $source -ItemType Directory -Force | Out-Null + New-Item $destination -ItemType Directory -Force | Out-Null + + $testFilePath = Join-Path $source "testfile.txt" + "File test content" | Out-File $testFilePath -Force + + # Keep track of the sessions. + $testSessions = @{} + + # Keep track of the session names to be unregistered. + $sessionToUnregister = @() + + $languageModes = @("ConstrainedLanguage", "NoLanguage", "RestrictedLanguage") + $id = (Get-Random).ToString() + + foreach ($languageMode in $languageModes) + { + $sessionName = $languageMode + "_" + $id + $sessionToUnregister += $sessionName + $configFilePath = Join-Path $testDirectory "test.pssc" + + # Create the session. + Write-Host "Creating pssession with '$languageMode' ..." + New-PSSessionConfigurationFile -Path $configFilePath -SessionType Default -LanguageMode $languageMode + Register-PSSessionConfiguration -Name $sessionName -Path $configFilePath -Force | Out-Null + $testSession = New-PSSession -ConfigurationName $sessionName + + # Validate that the session is opened. + $testSession.State | Should Be "Opened" + + # Add the new session to the list. + $testSessions[$languageMode] = $testSession + + # Remove the pssc file. + Remove-Item $configFilePath -Force -ea SilentlyContinue + } + } + + AfterAll { + + $testSessions.Values | Remove-PSSession -ea SilentlyContinue + + $sessionToUnregister | foreach { + Unregister-PSSessionConfiguration -Name $_ -Force -ea SilentlyContinue + } + } + + foreach ($languageMode in $testSessions.Keys) + { + $session = $testSessions[$languageMode] + + It "Copy-Item throws 'SessionIsNotInFullLanguageMode' error for a session in '$languageMode'" { + + # FromSession + try + { + Copy-Item -Path $testFilePath -FromSession $session -Destination $destination -Force -Verbose -ea Stop + throw "CodeExecuted" + } + catch + { + $_.FullyQualifiedErrorId | should be "SessionIsNotInFullLanguageMode,Microsoft.PowerShell.Commands.CopyItemCommand" + } + + # ToSession + try + { + Copy-Item -Path $testFilePath -ToSession $session -Destination $destination -Force -Verbose -ea Stop + throw "CodeExecuted" + } + catch + { + $_.FullyQualifiedErrorId | should be "SessionIsNotInFullLanguageMode,Microsoft.PowerShell.Commands.CopyItemCommand" + } + } + } +} + +Describe "Copy-Item can use Recurse and Exclude together" -Tags "Feature" { + + Context "Local and Remote Tests" { + + BeforeAll { + $s = New-PSSession -ComputerName . -ea SilentlyContinue + if (-not $s) + { + throw "Failed to create PSSession for remote copy operations." + } + + $null = New-Item -ItemType Directory -Path "TestDrive:\Parent\Sub" + $null = New-Item -Path "TestDrive:\Parent\p1.txt" -Value "test" + $null = New-Item -Path "TestDrive:\Parent\p2.txt" -Value "test" + $null = New-Item -Path "TestDrive:\Parent\s4.txt" -Value "test" + $null = New-Item -Path "TestDrive:\Parent\Sub\s1.txt" -Value "test" + $null = New-Item -Path "TestDrive:\Parent\Sub\s2.txt" -Value "test" + $null = New-Item -Path "TestDrive:\Parent\Sub\s3.txt" -Value "test" + $null = New-Item -Path "TestDrive:\Parent\Sub\p3.txt" -Value "testcl" + } + + It "can exclude files at sub directory" { + Copy-Item -Path TestDrive:\Parent\* -Recurse -Exclude s*.txt -Destination TestDrive:\Temp -Force + $copiedFiles = Get-ChildItem -Recurse -Path TestDrive:\Temp + $copiedFiles.Count | Should Be 3 + } + + It "can exclude files at sub directory to a session" { + Copy-Item -Path TestDrive:\Parent\* -Recurse -Exclude s*.txt -Destination $TestDrive\Temp2 -Force -ToSession $s + $copiedFiles = Get-ChildItem -Recurse -Path TestDrive:\Temp + $copiedFiles.Count | Should Be 3 + } + + It "can exclude files at sub directory from a session" { + Copy-Item -Path $TestDrive\Parent\* -Recurse -Exclude s*.txt -Destination TestDrive:\Temp3 -FromSession $s + $copiedFiles = Get-ChildItem -Recurse -Path TestDrive:\Temp2 + $copiedFiles.Count | Should Be 3 + } + + AfterAll { + Remove-PSSession -Session $s -ErrorAction SilentlyContinue + } + } +} + +Describe "Copy-Item remotely bug fixes" -Tags "Feature" { + + BeforeAll { + $s = New-PSSession -ComputerName . -ErrorAction SilentlyContinue + if (-not $s) + { + throw "Failed to create PSSession for remote copy operations." + } + + $originalContent = "test file 1 - Source" + $newContent = "This is some new content" + + $null = New-Item -ItemType Directory -Path "TestDrive:\Source" + $null = New-Item -ItemType Directory -Path "TestDrive:\Destination" + } + + AfterAll { + Remove-PSSession -Session $s -ErrorAction SilentlyContinue + } + + BeforeEach { + + # Create the same file in the source and destination + Set-Content -Path "TestDrive:\Source\testFile1.txt" -Value $originalContent -Force + Set-Content -Path "TestDrive:\Destination\testFile1.txt" -Value $originalContent -Force + } + + Context "Copy-Item remotely overwrites a destination file if it exists." { + + BeforeEach { + + # Overwrite the source file + Set-Content -Path "TestDrive:\Source\testFile1.txt" -Value $newContent + } + + It "Copy item -tosession overwrites the content of an existing file." { + + # Copy file to session + Copy-Item -Path "TestDrive:\Source\testFile1.txt" -Destination "$TestDrive\Destination\testFile1.txt" -ToSession $s + + # Validate the the file was overwritten + $fileContent = Get-Content "TestDrive:\Destination\testFile1.txt" -ea SilentlyContinue -Raw + $fileContent | Should Match $newContent + } + + It "Copy item -fromsession overwrites the content of an existing file." { + + # Copy file to session + Copy-Item -Path "$TestDrive\Source\testFile1.txt" -Destination "TestDrive:\Destination\testFile1.txt" -FromSession $s + + # Validate the the file was overwritten + $fileContent = Get-Content "TestDrive:\Destination\testFile1.txt" -ea SilentlyContinue -Raw + $fileContent | Should Match $newContent + } + } + + Context "Copy-Item remotely creates a destination file if it does not exist." { + + BeforeEach { + + if (Test-Path "TestDrive:\AnotherDestination") + { + Remove-Item "TestDrive:\AnotherDestination" -Force -Recurse -ea SilentlyContinue + } + $null = New-Item -ItemType Directory -Path "TestDrive:\AnotherDestination" + + # Ensure the file does not exist + "TestDrive:\AnotherDestination\FileThatDoesNotExist.txt" | Should Not Exist + } + + It "Copy-Item -tosession creates the file if it does not exist on the remote destination." { + + # Copy file to session + Copy-Item -Path "TestDrive:\Source\testFile1.txt" -Destination "$TestDrive\AnotherDestination\FileThatDoesNotExist.txt" -ToSession $s + + # Verify that the file was created + "TestDrive:\AnotherDestination\FileThatDoesNotExist.txt" | Should Exist + } + + It "Copy-Item -fromsession creates the file if it does not exist on the local machine." { + + # Copy file from session + Copy-Item -Path "$TestDrive\Source\testFile1.txt" -Destination "TestDrive:\AnotherDestination\FileThatDoesNotExist.txt" -FromSession $s + + # Verify that the file was created + "TestDrive:\AnotherDestination\FileThatDoesNotExist.txt" | Should Exist + } + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Pester.Commands.Cmdlets.NoNewlineParameter.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Pester.Commands.Cmdlets.NoNewlineParameter.Tests.ps1 index 24941dc337..1be6c38dd8 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Pester.Commands.Cmdlets.NoNewlineParameter.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Pester.Commands.Cmdlets.NoNewlineParameter.Tests.ps1 @@ -1,26 +1,26 @@ -# Tests related to TFS item 1370133 [PSUpgrade] Need -NoNewline parameter on Out-File, Add-Content and Set-Content -# Connect request https://connect.microsoft.com/PowerShell/feedback/details/524739/need-nonewline-parameter-on-out-file-add-content-and-set-content - -Describe "Tests for -NoNewline parameter of Out-File, Add-Content and Set-Content" -tags "Feature" { - - It "NoNewline parameter works on Out-File" { - $temp = New-TemporaryFile - 1..5 | Out-File $temp.FullName -Encoding 'ASCII' -NoNewline - (Get-Content $temp -Encoding Byte).Count | Should Be 5 - Remove-Item $temp -ErrorAction SilentlyContinue -Force - } - - It "NoNewline parameter works on Set-Content" { - $temp = New-TemporaryFile - Set-Content -Path $temp.FullName -Value 'a','b','c' -Encoding 'ASCII' -NoNewline - (Get-Content $temp -Encoding Byte).Count | Should Be 3 - Remove-Item $temp -ErrorAction SilentlyContinue -Force - } - - It "NoNewline parameter works on Add-Content" { - $temp = New-TemporaryFile - 1..9 | %{Add-Content -Path $temp.FullName -Value $_ -Encoding 'ASCII' -NoNewline} - (Get-Content $temp -Encoding Byte).Count | Should Be 9 - Remove-Item $temp -ErrorAction SilentlyContinue -Force - } -} +# Tests related to TFS item 1370133 [PSUpgrade] Need -NoNewline parameter on Out-File, Add-Content and Set-Content +# Connect request https://connect.microsoft.com/PowerShell/feedback/details/524739/need-nonewline-parameter-on-out-file-add-content-and-set-content + +Describe "Tests for -NoNewline parameter of Out-File, Add-Content and Set-Content" -tags "Feature" { + + It "NoNewline parameter works on Out-File" { + $temp = New-TemporaryFile + 1..5 | Out-File $temp.FullName -Encoding 'ASCII' -NoNewline + (Get-Content $temp -Encoding Byte).Count | Should Be 5 + Remove-Item $temp -ErrorAction SilentlyContinue -Force + } + + It "NoNewline parameter works on Set-Content" { + $temp = New-TemporaryFile + Set-Content -Path $temp.FullName -Value 'a','b','c' -Encoding 'ASCII' -NoNewline + (Get-Content $temp -Encoding Byte).Count | Should Be 3 + Remove-Item $temp -ErrorAction SilentlyContinue -Force + } + + It "NoNewline parameter works on Add-Content" { + $temp = New-TemporaryFile + 1..9 | %{Add-Content -Path $temp.FullName -Value $_ -Encoding 'ASCII' -NoNewline} + (Get-Content $temp -Encoding Byte).Count | Should Be 9 + Remove-Item $temp -ErrorAction SilentlyContinue -Force + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/FormatHex.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/FormatHex.Tests.ps1 index b91c7aebd0..b5437fc7ef 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/FormatHex.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/FormatHex.Tests.ps1 @@ -1,221 +1,221 @@ -# This is a Pester test suite to validate the Format-Hex cmdlet in the Microsoft.PowerShell.Utility module. -# -# Copyright (c) Microsoft Corporation, 2015 -# - -<# - Purpose: - Verify that Format-Hex display the Hexa decmial value for the input data. - - Action: - Run Format-Fex. - - Expected Result: - Hexa decimal equivalent of the input data is displayed. -#> - -Describe "FormatHex" -tags "CI" { - BeforeAll { - Setup -d FormatHexDataDir - $inputText1 = 'Hello World' - $inputText2 = 'This is a bit more text' - $inputFile1 = setup -f "FormatHexDataDir/SourceFile-1.txt" -content $inputText1 -pass - $inputFile2 = setup -f "FormatHexDataDir/SourceFile-2.txt" -content $inputText2 -pass - } - - # This test is to validate to pipeline support in Format-Hex cmdlet. - It "ValidatePipelineSupport" { - - # InputObject Parameter set should get invoked and - # the input data should be treated as string. - $result = $inputText1 | Format-Hex - $result | Should Not Be $null - $result.GetType().Name | Should Be 'ByteCollection' - $actualResult = $result.ToString() - ($actualResult -match $inputText1) | Should Be $true - } - - # This test is to validate to pipeline support in Format-Hex cmdlet. - It "ValidateByteArrayInputSupport" { - - # InputObject Parameter set should get invoked and - # the input data should be treated as byte[]. - $inputBytes = [System.Text.Encoding]::ASCII.GetBytes($inputText1) - - $result = Format-Hex -InputObject $inputBytes - $result | Should Not Be $null - $result.GetType().Name | Should Be 'ByteCollection' - $actualResult = $result.ToString() - ($actualResult -match $inputText1) | Should Be $true - } - - # This test is to validate to input given through Path paramter set in Format-Hex cmdlet. - It "ValidatePathParameterSet" { - - $result = Format-Hex -Path $inputFile1 - $result | Should Not Be $null - $result.GetType().Name | Should Be 'ByteCollection' - $actualResult = $result.ToString() - ($actualResult -match $inputText1) | Should Be $true - } - - # This test is to validate to Path paramter set is considered as default in Format-Hex cmdlet. - It "ValidatePathAsDefaultParameterSet" { - - $result = Format-Hex $inputFile1 - $result | Should Not BeNullOrEmpty - $result.GetType().Name | Should Be 'ByteCollection' - $actualResult = $result.ToString() - ($actualResult -match $inputText1) | Should Be $true - } - - # This test is to validate to input given through LiteralPath paramter set in Format-Hex cmdlet. - It "ValidateLiteralPathParameterSet" { - - $result = Format-Hex -LiteralPath $inputFile1 - $result | Should Not BeNullOrEmpty - $result.GetType().Name | Should Be 'ByteCollection' - $actualResult = $result.ToString() - ($actualResult -match $inputText1) | Should Be $true - } - - # This test is to validate to input given through pipeline. The input being piped from results of Get-hildItem - It "ValidateFileInfoPipelineInput" { - - $result = Get-ChildItem $inputFile1 | Format-Hex - $result | Should Not BeNullOrEmpty - $result.GetType().Name | Should Be 'ByteCollection' - $actualResult = $result.ToString() - ($actualResult -match $inputText1) | Should Be $true - } - - # This test is to validate Encoding formats functionality of Format-Hex cmdlet. - It "ValidateEncodingFormats" { - - $result = Format-Hex -InputObject $inputText1 -Encoding ASCII - $result | Should Not BeNullOrEmpty - $result.GetType().Name | Should Be 'ByteCollection' - $actualResult = $result.ToString() - ($actualResult -match $inputText1) | Should Be $true - } - - # This test is to validate that integers can be piped to the format-hex - It "ValidateIntegerInput" { - - $result = 1,2,3,4 | Format-Hex - $result | Should Not BeNullOrEmpty - $result.GetType().Name | Should Be 'ByteCollection' - $actualResult = $result.ToString() - # whitespace sensitive - $actualResult | should be "00000000 01 02 03 04 .... " - } - - # This test is to validate that integers can be piped to the format-hex - # and properly represented as characters in the string - It "ValidateIntegerInputThatPresentAsCharacters" { - - $result = 65..68 | Format-Hex - $result | Should Not BeNullOrEmpty - $result.GetType().Name | Should Be 'ByteCollection' - $actualResult = $result.ToString() - # whitespace sensitive - $actualResult | should be "00000000 41 42 43 44 ABCD " - } - - # This test is to validate that integers can be piped to the format-hex - It "ValidateIntegerRawInput" { - - $result = 1,2,3,4 | Format-Hex -Raw - $result | Should Not BeNullOrEmpty - $result.GetType().Name | Should Be 'ByteCollection' - $actualResult = $result.ToString() - # whitespace sensitive - $actualResult | should be "00000000 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 ................" - } - - # handle int64 - It "ValidateInteger64" { - - $result = [int64]::MaxValue | Format-Hex - $result | Should Not BeNullOrEmpty - $result.GetType().Name | Should Be 'ByteCollection' - $actualResult = $result.ToString() - # whitespace sensitive - $actualResult | Should Match "00000000 FF FF FF FF FF FF FF 7F ." - } - - # handle bytes, int16, int32, and int64 - It "Validate combined and reduced number formatting" { - $b = 65 # fits in a byte - $i16 = 32767 # fits in an int16 - $i32 = 2147483647 # an int32 - $i64 = 9223372036854775807 # an int64 - $result = $b,$i16,$i32,$i64 | format-Hex - $result.GetType().Name | should be 'ByteCollection' - $actualResult = $result.ToString() - $actualResult | should Match "00000000 41 FF 7F FF FF FF 7F FF FF FF FF FF FF FF 7F A" - } - - # handle bytes, int16, int32, and int64 - It "Validate combined and with raw number formatting" { - $b = 65 # fits in a byte - $i16 = 32767 # fits in an int16 - $i32 = 2147483647 # an int32 - $i64 = 9223372036854775807 # an int64 - # this will cause 2 lines to be emitted - $result = $b,$i16,$i32,$i64 | format-Hex -Raw - $result[0].GetType().Name | should be 'ByteCollection' - $result[1].GetType().Name | should be 'ByteCollection' - $result0 = $result[0].ToString() - $result0 | should match "00000000 41 00 00 00 FF 7F 00 00 FF FF FF 7F FF FF FF FF A" - $result1 = $result[1].ToString() - $result1 | should match "00000010 FF FF FF 7F .." - } - - # This test is to validate that streamed text does not have buffer underrun problems - It "ValidateEachBufferHasCorrectContentForStreamingText" { - $result = "a" * 30 | Format-Hex - $result | Should Not BeNullOrEmpty - $result.GetType().Name | Should Be 'ByteCollection' - $actualResult = $result.ToString() -split "`r`n" - $actualResult.Count | should be 2 - $actualResult[0].ToString() | Should be "00000000 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 aaaaaaaaaaaaaaaa" - $actualResult[1].ToString() | Should be "00000010 61 61 61 61 61 61 61 61 61 61 61 61 61 61 aaaaaaaaaaaaaa " - } - - # This test is to validate that files do not have buffer underrun problems - It "ValidateEachBufferHasCorrectContentForFiles" { - $result = Format-Hex -path $InputFile2 - $result | Should Not BeNullOrEmpty - $result.Count | should be 2 - $result[0].ToString() | Should be "00000000 54 68 69 73 20 69 73 20 61 20 62 69 74 20 6D 6F This is a bit mo" - if ( $IsCore ) { - $result[1].ToString() | Should be "00000010 72 65 20 74 65 78 74 re text " - } - } - - # This test ensures that if we stream bytes from a file, the output is correct - It "ValidateStreamOfBytesFromFileHasProperOutput" { - $result = Get-Content $InputFile1 -Encoding Byte | Format-Hex - $result | Should Not BeNullOrEmpty - $result.GetType().Name | Should Be "ByteCollection" - if ( $IsCore ) { - $result.ToString() | Should be "00000000 48 65 6C 6C 6F 20 57 6F 72 6C 64 Hello World " - } - } - - # This test is to validate the alias for Format-Hex cmdlet. - It "ValidateCmdletAlias" { - - try - { - $result = Get-Command fhx -ErrorAction Stop - $result | Should Not BeNullOrEmpty - $result.CommandType.ToString() | Should Be "Alias" - } - catch - { - $_ | Should BeNullOrEmpty - } - } -} +# This is a Pester test suite to validate the Format-Hex cmdlet in the Microsoft.PowerShell.Utility module. +# +# Copyright (c) Microsoft Corporation, 2015 +# + +<# + Purpose: + Verify that Format-Hex display the Hexa decmial value for the input data. + + Action: + Run Format-Fex. + + Expected Result: + Hexa decimal equivalent of the input data is displayed. +#> + +Describe "FormatHex" -tags "CI" { + BeforeAll { + Setup -d FormatHexDataDir + $inputText1 = 'Hello World' + $inputText2 = 'This is a bit more text' + $inputFile1 = setup -f "FormatHexDataDir/SourceFile-1.txt" -content $inputText1 -pass + $inputFile2 = setup -f "FormatHexDataDir/SourceFile-2.txt" -content $inputText2 -pass + } + + # This test is to validate to pipeline support in Format-Hex cmdlet. + It "ValidatePipelineSupport" { + + # InputObject Parameter set should get invoked and + # the input data should be treated as string. + $result = $inputText1 | Format-Hex + $result | Should Not Be $null + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() + ($actualResult -match $inputText1) | Should Be $true + } + + # This test is to validate to pipeline support in Format-Hex cmdlet. + It "ValidateByteArrayInputSupport" { + + # InputObject Parameter set should get invoked and + # the input data should be treated as byte[]. + $inputBytes = [System.Text.Encoding]::ASCII.GetBytes($inputText1) + + $result = Format-Hex -InputObject $inputBytes + $result | Should Not Be $null + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() + ($actualResult -match $inputText1) | Should Be $true + } + + # This test is to validate to input given through Path paramter set in Format-Hex cmdlet. + It "ValidatePathParameterSet" { + + $result = Format-Hex -Path $inputFile1 + $result | Should Not Be $null + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() + ($actualResult -match $inputText1) | Should Be $true + } + + # This test is to validate to Path paramter set is considered as default in Format-Hex cmdlet. + It "ValidatePathAsDefaultParameterSet" { + + $result = Format-Hex $inputFile1 + $result | Should Not BeNullOrEmpty + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() + ($actualResult -match $inputText1) | Should Be $true + } + + # This test is to validate to input given through LiteralPath paramter set in Format-Hex cmdlet. + It "ValidateLiteralPathParameterSet" { + + $result = Format-Hex -LiteralPath $inputFile1 + $result | Should Not BeNullOrEmpty + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() + ($actualResult -match $inputText1) | Should Be $true + } + + # This test is to validate to input given through pipeline. The input being piped from results of Get-hildItem + It "ValidateFileInfoPipelineInput" { + + $result = Get-ChildItem $inputFile1 | Format-Hex + $result | Should Not BeNullOrEmpty + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() + ($actualResult -match $inputText1) | Should Be $true + } + + # This test is to validate Encoding formats functionality of Format-Hex cmdlet. + It "ValidateEncodingFormats" { + + $result = Format-Hex -InputObject $inputText1 -Encoding ASCII + $result | Should Not BeNullOrEmpty + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() + ($actualResult -match $inputText1) | Should Be $true + } + + # This test is to validate that integers can be piped to the format-hex + It "ValidateIntegerInput" { + + $result = 1,2,3,4 | Format-Hex + $result | Should Not BeNullOrEmpty + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() + # whitespace sensitive + $actualResult | should be "00000000 01 02 03 04 .... " + } + + # This test is to validate that integers can be piped to the format-hex + # and properly represented as characters in the string + It "ValidateIntegerInputThatPresentAsCharacters" { + + $result = 65..68 | Format-Hex + $result | Should Not BeNullOrEmpty + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() + # whitespace sensitive + $actualResult | should be "00000000 41 42 43 44 ABCD " + } + + # This test is to validate that integers can be piped to the format-hex + It "ValidateIntegerRawInput" { + + $result = 1,2,3,4 | Format-Hex -Raw + $result | Should Not BeNullOrEmpty + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() + # whitespace sensitive + $actualResult | should be "00000000 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 ................" + } + + # handle int64 + It "ValidateInteger64" { + + $result = [int64]::MaxValue | Format-Hex + $result | Should Not BeNullOrEmpty + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() + # whitespace sensitive + $actualResult | Should Match "00000000 FF FF FF FF FF FF FF 7F ." + } + + # handle bytes, int16, int32, and int64 + It "Validate combined and reduced number formatting" { + $b = 65 # fits in a byte + $i16 = 32767 # fits in an int16 + $i32 = 2147483647 # an int32 + $i64 = 9223372036854775807 # an int64 + $result = $b,$i16,$i32,$i64 | format-Hex + $result.GetType().Name | should be 'ByteCollection' + $actualResult = $result.ToString() + $actualResult | should Match "00000000 41 FF 7F FF FF FF 7F FF FF FF FF FF FF FF 7F A" + } + + # handle bytes, int16, int32, and int64 + It "Validate combined and with raw number formatting" { + $b = 65 # fits in a byte + $i16 = 32767 # fits in an int16 + $i32 = 2147483647 # an int32 + $i64 = 9223372036854775807 # an int64 + # this will cause 2 lines to be emitted + $result = $b,$i16,$i32,$i64 | format-Hex -Raw + $result[0].GetType().Name | should be 'ByteCollection' + $result[1].GetType().Name | should be 'ByteCollection' + $result0 = $result[0].ToString() + $result0 | should match "00000000 41 00 00 00 FF 7F 00 00 FF FF FF 7F FF FF FF FF A" + $result1 = $result[1].ToString() + $result1 | should match "00000010 FF FF FF 7F .." + } + + # This test is to validate that streamed text does not have buffer underrun problems + It "ValidateEachBufferHasCorrectContentForStreamingText" { + $result = "a" * 30 | Format-Hex + $result | Should Not BeNullOrEmpty + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() -split "`r`n" + $actualResult.Count | should be 2 + $actualResult[0].ToString() | Should be "00000000 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 aaaaaaaaaaaaaaaa" + $actualResult[1].ToString() | Should be "00000010 61 61 61 61 61 61 61 61 61 61 61 61 61 61 aaaaaaaaaaaaaa " + } + + # This test is to validate that files do not have buffer underrun problems + It "ValidateEachBufferHasCorrectContentForFiles" { + $result = Format-Hex -path $InputFile2 + $result | Should Not BeNullOrEmpty + $result.Count | should be 2 + $result[0].ToString() | Should be "00000000 54 68 69 73 20 69 73 20 61 20 62 69 74 20 6D 6F This is a bit mo" + if ( $IsCore ) { + $result[1].ToString() | Should be "00000010 72 65 20 74 65 78 74 re text " + } + } + + # This test ensures that if we stream bytes from a file, the output is correct + It "ValidateStreamOfBytesFromFileHasProperOutput" { + $result = Get-Content $InputFile1 -Encoding Byte | Format-Hex + $result | Should Not BeNullOrEmpty + $result.GetType().Name | Should Be "ByteCollection" + if ( $IsCore ) { + $result.ToString() | Should be "00000000 48 65 6C 6C 6F 20 57 6F 72 6C 64 Hello World " + } + } + + # This test is to validate the alias for Format-Hex cmdlet. + It "ValidateCmdletAlias" { + + try + { + $result = Get-Command fhx -ErrorAction Stop + $result | Should Not BeNullOrEmpty + $result.CommandType.ToString() | Should Be "Alias" + } + catch + { + $_ | Should BeNullOrEmpty + } + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/ImportExportCSV.Delimiter.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/ImportExportCSV.Delimiter.Tests.ps1 index 73aa5a9b87..04bc41d895 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/ImportExportCSV.Delimiter.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/ImportExportCSV.Delimiter.Tests.ps1 @@ -1,84 +1,84 @@ -Describe "Using delimiters with Export-CSV and Import-CSV behave correctly" -tags "Feature" { - BeforeAll { - # note, we will not use "," as that's the default for CSV - $delimiters = "/", " ", "@", "#", "$", "\", "&", "(", ")", - "{", "}", "|", "<", ">", ";", "'", - '"', "~", "!", "%", "^", "*", "_", "+", ":", - "?", "-", "=", "[", "]", "." - $defaultDelimiter = [System.Globalization.CultureInfo]::CurrentCulture.TextInfo.ListSeparator - # With CORECLR the CurrentCulture.TextInfo.ListSeparator is not writable, so - # we need to use an entirely new CultureInfo which we can modify - $enCulture = [System.Globalization.CultureInfo]::new("en-us") - $d = get-date - $testCases = @( - foreach($del in $delimiters) - { - @{ Delimiter = $del; Data = $d; ExpectedResult = $d.Ticks } - } - ) - function Set-delimiter { - param ( $delimiter ) - if ( $IsCore ) { - $enCulture.TextInfo.ListSeparator = $delimiter - [System.Globalization.CultureInfo]::CurrentCulture = $enCulture - } - else { - [System.Globalization.cultureInfo]::CurrentCulture.TextInfo.ListSeparator = $delimiter - } - } - } - AfterEach { - if ( $IsCore ) { - $enCulture.TextInfo.ListSeparator = $defaultDelimiter - [System.Globalization.CultureInfo]::CurrentCulture = $enCulture - } - else { - [System.Globalization.CultureInfo]::CurrentCulture.TextInfo.ListSeparator = $defaultDelimiter - } - remove-item -force -ea silentlycontinue TESTDRIVE:/file.csv - } - - It "Disallow use of null delimiter" { - $d | export-csv TESTDRIVE:/file.csv - { import-csv -path TESTDRIVE:/file.csv -delimiter $null } | Should Throw "Delimiter" - } - - It "Disallow use of delimiter with useCulture parameter" { - $d | export-csv TESTDRIVE:/file.csv - { import-csv -path TESTDRIVE:/file.csv -useCulture "," } | Should Throw "','" - } - - It "Imports the same properties as exported" { - $a = [pscustomobject]@{ a = 1; b = 2; c = 3 } - $a | export-Csv TESTDRIVE:/file.csv - $b = import-csv TESTDRIVE:/file.csv - @($b.psobject.properties).count | should be 3 - $b.a | Should be $a.a - $b.b | Should be $a.b - $b.c | Should be $a.c - } - - # parameter generated tests - It 'Delimiter with CSV import will fail correctly when culture does not match' -testCases $testCases { - param ($delimiter, $Data, $ExpectedResult) - set-Delimiter $delimiter - $Data | export-CSV TESTDRIVE:\File.csv -useCulture - $i = Import-CSV TESTDRIVE:\File.csv - $i.Ticks | Should Not Be $ExpectedResult - } - - It 'Delimiter with CSV import will succeed when culture matches export' -testCases $testCases { - param ($delimiter, $Data, $ExpectedResult) - set-Delimiter $delimiter - $Data | export-CSV TESTDRIVE:\File.csv -useCulture - $i = Import-CSV TESTDRIVE:\File.csv -useCulture - $i.Ticks | Should Be $ExpectedResult - } - - It 'Delimiter with CSV import will succeed when delimiter is used explicitly' -testCases $testCases { - param ($delimiter, $Data, $ExpectedResult) - $Data | export-CSV TESTDRIVE:\File.csv -delimiter $delimiter - $i = Import-CSV TESTDRIVE:\File.csv -delimiter $delimiter - $i.Ticks | Should Be $ExpectedResult - } -} +Describe "Using delimiters with Export-CSV and Import-CSV behave correctly" -tags "Feature" { + BeforeAll { + # note, we will not use "," as that's the default for CSV + $delimiters = "/", " ", "@", "#", "$", "\", "&", "(", ")", + "{", "}", "|", "<", ">", ";", "'", + '"', "~", "!", "%", "^", "*", "_", "+", ":", + "?", "-", "=", "[", "]", "." + $defaultDelimiter = [System.Globalization.CultureInfo]::CurrentCulture.TextInfo.ListSeparator + # With CORECLR the CurrentCulture.TextInfo.ListSeparator is not writable, so + # we need to use an entirely new CultureInfo which we can modify + $enCulture = [System.Globalization.CultureInfo]::new("en-us") + $d = get-date + $testCases = @( + foreach($del in $delimiters) + { + @{ Delimiter = $del; Data = $d; ExpectedResult = $d.Ticks } + } + ) + function Set-delimiter { + param ( $delimiter ) + if ( $IsCore ) { + $enCulture.TextInfo.ListSeparator = $delimiter + [System.Globalization.CultureInfo]::CurrentCulture = $enCulture + } + else { + [System.Globalization.cultureInfo]::CurrentCulture.TextInfo.ListSeparator = $delimiter + } + } + } + AfterEach { + if ( $IsCore ) { + $enCulture.TextInfo.ListSeparator = $defaultDelimiter + [System.Globalization.CultureInfo]::CurrentCulture = $enCulture + } + else { + [System.Globalization.CultureInfo]::CurrentCulture.TextInfo.ListSeparator = $defaultDelimiter + } + remove-item -force -ea silentlycontinue TESTDRIVE:/file.csv + } + + It "Disallow use of null delimiter" { + $d | export-csv TESTDRIVE:/file.csv + { import-csv -path TESTDRIVE:/file.csv -delimiter $null } | Should Throw "Delimiter" + } + + It "Disallow use of delimiter with useCulture parameter" { + $d | export-csv TESTDRIVE:/file.csv + { import-csv -path TESTDRIVE:/file.csv -useCulture "," } | Should Throw "','" + } + + It "Imports the same properties as exported" { + $a = [pscustomobject]@{ a = 1; b = 2; c = 3 } + $a | export-Csv TESTDRIVE:/file.csv + $b = import-csv TESTDRIVE:/file.csv + @($b.psobject.properties).count | should be 3 + $b.a | Should be $a.a + $b.b | Should be $a.b + $b.c | Should be $a.c + } + + # parameter generated tests + It 'Delimiter with CSV import will fail correctly when culture does not match' -testCases $testCases { + param ($delimiter, $Data, $ExpectedResult) + set-Delimiter $delimiter + $Data | export-CSV TESTDRIVE:\File.csv -useCulture + $i = Import-CSV TESTDRIVE:\File.csv + $i.Ticks | Should Not Be $ExpectedResult + } + + It 'Delimiter with CSV import will succeed when culture matches export' -testCases $testCases { + param ($delimiter, $Data, $ExpectedResult) + set-Delimiter $delimiter + $Data | export-CSV TESTDRIVE:\File.csv -useCulture + $i = Import-CSV TESTDRIVE:\File.csv -useCulture + $i.Ticks | Should Be $ExpectedResult + } + + It 'Delimiter with CSV import will succeed when delimiter is used explicitly' -testCases $testCases { + param ($delimiter, $Data, $ExpectedResult) + $Data | export-CSV TESTDRIVE:\File.csv -delimiter $delimiter + $i = Import-CSV TESTDRIVE:\File.csv -delimiter $delimiter + $i.Ticks | Should Be $ExpectedResult + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/MiscCmdletUpdates.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/MiscCmdletUpdates.Tests.ps1 index 831a1292ac..c7a1f73f50 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/MiscCmdletUpdates.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/MiscCmdletUpdates.Tests.ps1 @@ -1,54 +1,54 @@ -Describe "GetDateFormatUpdates" -Tags "Feature" { - - It "Verifies that FileDate format works" { - $date = Get-Date - $expectedFormat = "{0:yyyyMMdd}" -f $date - $actualFormat = Get-Date -Date $date -Format FileDate - - $actualFormat | Should be $expectedFormat - } - - It "Verifies that FileDateUniversal format works" { - $date = (Get-Date).ToUniversalTime() - $expectedFormat = "{0:yyyyMMddZ}" -f $date - $actualFormat = Get-Date -Date $date -Format FileDateUniversal - - $actualFormat | Should be $expectedFormat - } - - It "Verifies that FileDateTime format works" { - $date = Get-Date - $expectedFormat = "{0:yyyyMMddTHHmmssffff}" -f $date - $actualFormat = Get-Date -Date $date -Format FileDateTime - - $actualFormat | Should be $expectedFormat - } - - It "Verifies that FileDateTimeUniversal format works" { - $date = (Get-Date).ToUniversalTime() - $expectedFormat = "{0:yyyyMMddTHHmmssffffZ}" -f $date - $actualFormat = Get-Date -Date $date -Format FileDateTimeUniversal - - $actualFormat | Should be $expectedFormat - } - -} - -Describe "GetRandomMiscTests" -Tags "Feature" { - It "Shouldn't overflow when using max range" { - - $hadError = $false - - try - { - ## Don't actually need to validate - Get-Random -Minimum ([Int32]::MinValue) -Maximum ([Int32]::MaxValue) -ErrorAction Stop - } - catch - { - $hadError = $true - } - - $hadError | Should be $false - } -} +Describe "GetDateFormatUpdates" -Tags "Feature" { + + It "Verifies that FileDate format works" { + $date = Get-Date + $expectedFormat = "{0:yyyyMMdd}" -f $date + $actualFormat = Get-Date -Date $date -Format FileDate + + $actualFormat | Should be $expectedFormat + } + + It "Verifies that FileDateUniversal format works" { + $date = (Get-Date).ToUniversalTime() + $expectedFormat = "{0:yyyyMMddZ}" -f $date + $actualFormat = Get-Date -Date $date -Format FileDateUniversal + + $actualFormat | Should be $expectedFormat + } + + It "Verifies that FileDateTime format works" { + $date = Get-Date + $expectedFormat = "{0:yyyyMMddTHHmmssffff}" -f $date + $actualFormat = Get-Date -Date $date -Format FileDateTime + + $actualFormat | Should be $expectedFormat + } + + It "Verifies that FileDateTimeUniversal format works" { + $date = (Get-Date).ToUniversalTime() + $expectedFormat = "{0:yyyyMMddTHHmmssffffZ}" -f $date + $actualFormat = Get-Date -Date $date -Format FileDateTimeUniversal + + $actualFormat | Should be $expectedFormat + } + +} + +Describe "GetRandomMiscTests" -Tags "Feature" { + It "Shouldn't overflow when using max range" { + + $hadError = $false + + try + { + ## Don't actually need to validate + Get-Random -Minimum ([Int32]::MinValue) -Maximum ([Int32]::MaxValue) -ErrorAction Stop + } + catch + { + $hadError = $true + } + + $hadError | Should be $false + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/NewGuid.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/NewGuid.Tests.ps1 index 39757d61d9..95fc37cf02 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/NewGuid.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/NewGuid.Tests.ps1 @@ -1,19 +1,19 @@ -Describe "New-Guid" -Tags "CI" { - - It "returns a new guid" { - $guid = New-Guid - $guid.GetType().FullName | Should Be "System.Guid" - } - - It "should not be all zeros" { - $guid = New-Guid - $guid.ToString() | Should Not Be "00000000-0000-0000-0000-000000000000" - } - - It "should return different guids with each call" { - $guid1 = New-Guid - $guid2 = New-Guid - $guid1.ToString() | Should Not Be $guid2.ToString() - } -} - +Describe "New-Guid" -Tags "CI" { + + It "returns a new guid" { + $guid = New-Guid + $guid.GetType().FullName | Should Be "System.Guid" + } + + It "should not be all zeros" { + $guid = New-Guid + $guid.ToString() | Should Not Be "00000000-0000-0000-0000-000000000000" + } + + It "should return different guids with each call" { + $guid1 = New-Guid + $guid2 = New-Guid + $guid1.ToString() | Should Not Be $guid2.ToString() + } +} + diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/NewTemporaryFile.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/NewTemporaryFile.Tests.ps1 index 0c496b4a58..87bbefb3ba 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/NewTemporaryFile.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/NewTemporaryFile.Tests.ps1 @@ -1,38 +1,38 @@ -# This is a Pester test suite to validate the New-TemporaryFile cmdlet in the Microsoft.PowerShell.Utility module. -# -# Copyright (c) Microsoft Corporation, 2015 -# - -<# - Purpose: - Verify that New-TemporaryFile creates a temporary file. - - Action: - Run New-TemporaryFile. - - Expected Result: - A FileInfo object for the temporary file is returned. -#> - -Describe "NewTemporaryFile" -Tags "CI" { - - It "creates a new temporary file" { - $tempFile = New-TemporaryFile - - Test-Path $tempFile | Should be $true - $tempFile.GetType().Name | Should be "FileInfo" - - if(Test-Path $tempFile) - { - Remove-Item $tempFile -ErrorAction SilentlyContinue -Force - } - } - - It "with WhatIf does not create a file" { - New-TemporaryFile -WhatIf | Should Be $null - } - - It "has an OutputType of System.IO.FileInfo" { - (Get-Command New-TemporaryFile).OutputType | Should Be "System.IO.FileInfo" - } -} +# This is a Pester test suite to validate the New-TemporaryFile cmdlet in the Microsoft.PowerShell.Utility module. +# +# Copyright (c) Microsoft Corporation, 2015 +# + +<# + Purpose: + Verify that New-TemporaryFile creates a temporary file. + + Action: + Run New-TemporaryFile. + + Expected Result: + A FileInfo object for the temporary file is returned. +#> + +Describe "NewTemporaryFile" -Tags "CI" { + + It "creates a new temporary file" { + $tempFile = New-TemporaryFile + + Test-Path $tempFile | Should be $true + $tempFile.GetType().Name | Should be "FileInfo" + + if(Test-Path $tempFile) + { + Remove-Item $tempFile -ErrorAction SilentlyContinue -Force + } + } + + It "with WhatIf does not create a file" { + New-TemporaryFile -WhatIf | Should Be $null + } + + It "has an OutputType of System.IO.FileInfo" { + (Get-Command New-TemporaryFile).OutputType | Should Be "System.IO.FileInfo" + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.Json.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.Json.Tests.ps1 index da48d6dd7a..74c1c9312f 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.Json.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.Json.Tests.ps1 @@ -1,1466 +1,1425 @@ -# -# Copyright (c) Microsoft Corporation, 2015 -# -# This is a Pester test suite which validate the Json cmdlets. -# - -# -# This 'Describe' is for tests that were converted from utscripts (SDXROOT/admin/monad/tests/monad/DRT/utscripts) -# and C# tests (SDXROOT/admin/monad/tests/monad/DRT/commands/utility/UnitTests) to Pester. -# -Describe "Json Tests" -Tags "Feature" { - - BeforeAll { - - function ValidateSampleObject - { - param ($result, [switch]$hasEmbeddedSampleObject ) - - Write-Verbose "validating deserialized SampleObject" -Verbose - $result.SampleInt | Should Be 98765 - $result.SampleString | Should Match "stringVal" - $result.SampleArray.Count | Should Be 2 - $result.SampleTrue | Should Be $true - $result.SampleFalse | Should Be $false - $result.SampleNull | Should Be $null - $result.SampleFloat | Should Be 9.8765E+43 - - if ($hasEmbeddedSampleObject) - { - Write-Verbose "validating deserialized Embedded SampleObject" -Verbose - ValidateSampleObject -result $result.SampleObject - } - } - - } - - Context "ConvertTo-Json Bug Fixes" { - - It "ConvertTo-JSON should not have hard coded english error message" { - - # Test follow-up for bug WinBlue: 163372 - ConvertTo-JSON has hard coded english error message. - $process = Get-Process -Id $PID - $hash = @{ $process = "def" } - $expectedFullyQualifiedErrorId = "NonStringKeyInDictionary,Microsoft.PowerShell.Commands.ConvertToJsonCommand" - - try - { - ConvertTo-Json -InputObject $hash - throw "CodeExecuted" - } - catch - { - $_.FullyQualifiedErrorId | should be $expectedFullyQualifiedErrorId - } - } - - It "ConvertTo-Json should handle terms with double quotes" { - - # Test follow-up for bug WinBlue: 11484 - ConvertTo-Json can't handle terms with double quotes. - - $notcompressed = ConvertTo-JSON @{ FirstName = 'Hello " World' } - $compressed = ConvertTo-Json @{ FirstName = 'Hello " World' } -Compress - $valueFromNotCompressedResult = ConvertFrom-Json -InputObject $notcompressed - $valueFromCompressedResult = ConvertFrom-Json -InputObject $compressed - - $valueFromNotCompressedResult.FirstName | Should Match $valueFromCompressedResult.FirstName - } - - It "Convertto-Json should handle Enum based on Int64" { - - # Test follow-up for bug Win8: 378368 Convertto-Json problems with Enum based on Int64. - $src = @" -namespace Bug378368 -{ - public enum TestEnum : ulong - { - One = 1, - Two = 2 - } - - public enum TestEnum1 : long - { - One = 1, - Two = 2 - } - - public enum TestEnum2 : int - { - One = 1, - Two = 2 - } - - public class Test - { - public TestEnum TestEnum - { - get { return testEnum; } - set { testEnum = value; } - } - - private TestEnum testEnum = TestEnum.One; - - public TestEnum1 TestEnum1 - { - get { return testEnum1; } - set { testEnum1 = value; } - } - - private TestEnum1 testEnum1 = TestEnum1.Two; - - public TestEnum2 TestEnum2 - { - get { return testEnum2; } - set { testEnum2 = value; } - } - - private TestEnum2 testEnum2 = TestEnum2.One; - } -} -"@ - Add-Type $src - $op = new-object Bug378368.Test | convertto-json | convertfrom-json - $op.TestEnum | Should Be "One" - $op.TestEnum1 | Should Be "Two" - $op.TestEnum2 | Should Be 1 - } - - It "Test followup for Windows 8 bug 121627" { - - $JsonString = Get-Command Get-help |Select-Object Name, Noun, Verb| ConvertTo-Json - $actual = ConvertFrom-Json $JsonString - - $actual.Name | Should Be "Get-Help" - $actual.Noun | Should Be "Help" - $actual.Verb | Should Be "Get" - } - } - - Context "ConvertFrom and ConvertTo on JsonObject Tests" { - - It "Convert dictionary to PSObject" { - - $response = ConvertFrom-Json '{"d":{"__type":"SimpleJsonObject","Name":{"First":"Joel","Last":"Wood"},"Greeting":"Hello"}}' - $response.d.Name.First | Should Match "Joel" - } - - It "Convert to Json using PSObject" -pending:($IsCore) { - - $response = ConvertFrom-Json '{"d":{"__type":"SimpleJsonObject","Name":{"First":"Joel","Last":"Wood"},"Greeting":"Hello"}}' - - $response2 = ConvertTo-Json -InputObject $response -ErrorAction Continue - $response2 = ConvertTo-Json -InputObject $response -ErrorAction Inquire - $response2 = ConvertTo-Json -InputObject $response -ErrorAction SilentlyContinue - $response2 = ConvertTo-Json -InputObject $response -Depth 2 -Compress - $response2 | Should Be '{"d":{"Name":{"First":"Joel","Last":"Wood"},"Greeting":"Hello"}}' - - $response2 = ConvertTo-Json -InputObject $response -Depth 1 -Compress - $nameString = [System.Management.Automation.LanguagePrimitives]::ConvertTo($response.d.Name, [string]) - $response2 | Should Be "{`"d`":{`"Name`":`"$nameString`",`"Greeting`":`"Hello`"}}" - - $result1 = @" -{ - "d": { - "Name": { - "First": "Joel", - "Last": "Wood" - }, - "Greeting": "Hello" - } -} -"@ - $response2 = ConvertTo-Json -InputObject $response -Depth 2 - $response2 | Should Match $result1 - - $result2 = @" -{ - "d": { - "Name": "$nameString", - "Greeting": "Hello" - } -} -"@ - $response2 = ConvertTo-Json -InputObject $response -Depth 1 - $response2 | Should Match $result2 - - $arraylist = new-Object System.Collections.ArrayList - [void]$arraylist.Add("one") - [void]$arraylist.Add("two") - [void]$arraylist.Add("three") - $response2 = ConvertTo-Json -InputObject $arraylist -Compress - $response2 | Should Be '["one","two","three"]' - - $result3 = @" -[ - "one", - "two", - "three" -] -"@ - $response2 = ConvertTo-Json -InputObject $arraylist - $response2 | Should Be $result3 - - $response2 = $arraylist | ConvertTo-Json - $response2 | Should Be $result3 - } - - It "Convert to Json using hashtable" -pending:($IsCore) { - - $nameHash = @{First="Joe1";Last="Wood"} - $dHash = @{Name=$nameHash; Greeting="Hello"} - $rootHash = @{d=$dHash} - $response3 = ConvertTo-Json -InputObject $rootHash -Depth 2 -Compress - $response3 | Should Be '{"d":{"Greeting":"Hello","Name":{"Last":"Wood","First":"Joe1"}}}' - - $response3 = ConvertTo-Json -InputObject $rootHash -Depth 1 -Compress - $response3 | Should Be '{"d":{"Greeting":"Hello","Name":"System.Collections.Hashtable"}}' - - $result4 = @" -{ - "d": { - "Greeting": "Hello", - "Name": { - "Last": "Wood", - "First": "Joe1" - } - } -} -"@ - $response3 = ConvertTo-Json -InputObject $rootHash -Depth 2 - $response3 | Should Be $result4 - - $result5 = @" -{ - "d": { - "Greeting": "Hello", - "Name": "System.Collections.Hashtable" - } -} -"@ - $response3 = ConvertTo-Json -InputObject $rootHash -Depth 1 - $response3 | Should Be $result5 - } - - It "Convert from Json allows an empty string" { - - $emptyStringResult = ConvertFrom-Json "" - $emptyStringResult | Should Be $null - } - } - - Context "JsonObject Tests" { - - It "AddMember on JsonObject" { - - # create a Version object - $versionObject = New-Object System.Version 2, 3, 4, 14 - - # add a NoteProperty member called Note with a text note - $versionObject | Add-Member -MemberType NoteProperty -Name Note -Value "a version object" - - # add an AliasProperty called Rev as an alias to the Revison property - $versionObject | Add-Member -MemberType AliasProperty -Name Rev -Value Revision - - # add a ScriptProperty called IsOld which returns whether the version is an older version - $versionObject | Add-Member -MemberType ScriptProperty -Name IsOld -Value { ($this.Major -le 3) } - - $jstr = ConvertTo-Json $versionObject - - # convert the JSON string to a JSON object - $json = ConvertFrom-Json $jstr - - # Check the basic properties - $json.Major | Should Be 2 - $json.Minor | Should Be 3 - $json.Build | Should Be 4 - $json.Revision | Should Be 14 - $json.Note | Should Match "a version object" - - # Check the AliasProperty - $json.Rev | Should Be $json.Revision - - # Check the ScriptProperty - $json.IsOld | Should Be $true - } - - It "ConvertFrom-Json with a key value pair" { - - $json = "{name:1}" - $result = ConvertFrom-Json $json - $result.name | Should Be 1 - } - - It "ConvertFrom-Json with a simple array" { - - $json = "[1,2,3,4,5,6]" - $result = ConvertFrom-Json $json - $result.Count | Should Be 6 - $result.GetType().BaseType.fullname | Should Be "System.Array" - } - - It "ConvertFrom-Json with a float value" { - - $json = '{"SampleFloat1":1.2345E67, "SampleFloat2":-7.6543E-12}' - $result = ConvertFrom-Json $json - - $sampleFloat1 = Invoke-Expression 1.2345E67 - $result.SampleFloat1 | Should Be $sampleFloat1 - - $sampleFloat2 = Invoke-Expression -7.6543E-12 - $result.SampleFloat2 | Should Be $sampleFloat2 - } - - It "ConvertFrom-Json hash table nested in array" { - - $json = "['one', 'two', {'First':1,'Second':2,'Third':['Five','Six', 'Seven']}, 'four']" - $result = ConvertFrom-Json $json - - $result.Count | Should Be 4 - $result[0] | Should Be "one" - $result[1] | Should Be "two" - $result[3] | Should Be "four" - - $hash = $result[2] - $hash.First | Should Be 1 - $hash.Second | Should Be 2 - $hash.Third.Count | Should Be 3 - $hash.Third[0] | Should Be "Five" - $hash.Third[1] | Should Be "Six" - $hash.Third[2] | Should Be "Seven" - } - - It "ConvertFrom-Json array nested in hash table" { - - $json = '{"First":["one", "two", "three"], "Second":["four", "five"], "Third": {"blah": 4}}' - $result = ConvertFrom-Json $json - - $result.First.Count | Should Be 3 - $result.First[0] | Should Be "one" - $result.First[1] | Should Be "two" - $result.First[2] | Should Be "three" - - $result.Second.Count | Should Be 2 - $result.Second[0] | Should Be "four" - $result.Second[1] | Should Be "five" - - $result.Third.blah | Should Be "4" - } - - It "ConvertFrom-Json case insensitive test" { - - $json = '{"sAMPleValUE":12345}' - $result = ConvertFrom-Json $json - - $result.SampleValue | Should Be 12345 - } - - - It "ConvertFrom-Json sample values" { - - $json = '{"SampleInt":98765, "SampleString":"stringVal","SampleArray":[2,"two"], "SampleTrue":true, "SampleFalse":false,"SampleNull":null, "SampleFloat":9.8765E43}' - $result = ConvertFrom-Json $json - - # Validate the result object - ValidateSampleObject -result $result - - - $json = '{"SampleInt":98765, "SampleString":"stringVal","SampleArray":[2,"two"], "SampleTrue":true, ' + - '"SampleFalse":false,"SampleNull":null, "SampleFloat":9.8765E43, "SampleObject":'+ - '{"SampleInt":98765, "SampleString":"stringVal","SampleArray":[2,"two"], '+ - '"SampleTrue":true, "SampleFalse":false,"SampleNull":null, "SampleFloat":9.8765E43}}' - - # Validate the result object - $result = ConvertFrom-Json $json - ValidateSampleObject -result $result -hasEmbeddedSampleObject - } - - It "ConvertFrom-Json with special characters" { - - $json = '{"SampleValue":"\"\\\b\f\n\r\t\u4321\uD7FF"}' - $result = ConvertFrom-Json $json - $result.SampleValue[0] | Should Be '"' - $result.SampleValue[1] | Should Be '\' - $result.SampleValue[2] | Should Be 0x8 - $result.SampleValue[3] | Should Be 0xC - $result.SampleValue[4] | Should Be 0xA - $result.SampleValue[5] | Should Be 0xD - $result.SampleValue[6] | Should Be 0x9 - $result.SampleValue[7] | Should Be 0x4321 - $result.SampleValue[8] | Should Be 0xD7FF - } - } -} - -# This Describe is for new Json tests -# -Describe "Validate Json serialization" -Tags "CI" { - - Context "Validate Json serialization ascii values" { - - $testCases = @( - @{ - TestInput = 0 - ToJson = if ( $IsCore ) { '"\u0000"' } else { 'null' } - FromJson = '' - } - @{ - TestInput = 1 - ToJson = '"\u0001"' - FromJson = '' - } - @{ - TestInput = 2 - ToJson = '"\u0002"' - FromJson = '' - } - @{ - TestInput = 3 - ToJson = '"\u0003"' - FromJson = '' - } - @{ - TestInput = 4 - ToJson = '"\u0004"' - FromJson = '' - } - @{ - TestInput = 5 - ToJson = '"\u0005"' - FromJson = '' - } - @{ - TestInput = 6 - ToJson = '"\u0006"' - FromJson = '' - } - @{ - TestInput = 7 - ToJson = '"\u0007"' - FromJson = '' - } - @{ - TestInput = 8 - ToJson = '"\b"' - FromJson = '' - } - @{ - TestInput = 9 - ToJson = '"\t"' - FromJson = ' ' - } - @{ - TestInput = 10 - ToJson = '"\n"' - FromJson = "`n" - } - @{ - TestInput = 11 - ToJson = '"\u000b"' - FromJson = ' ' - } - @{ - TestInput = 12 - ToJson = '"\f"' - FromJson = ' ' - } - @{ - TestInput = 13 - ToJson = '"\r"' - FromJson = '' - } - @{ - TestInput = 14 - ToJson = '"\u000e"' - FromJson = '' - } - @{ - TestInput = 15 - ToJson = '"\u000f"' - FromJson = '' - } - @{ - TestInput = 16 - ToJson = '"\u0010"' - FromJson = '' - } - @{ - TestInput = 17 - ToJson = '"\u0011"' - FromJson = '' - } - @{ - TestInput = 18 - ToJson = '"\u0012"' - FromJson = '' - } - @{ - TestInput = 19 - ToJson = '"\u0013"' - FromJson = '' - } - @{ - TestInput = 20 - ToJson = '"\u0014"' - FromJson = '' - } - @{ - TestInput = 21 - ToJson = '"\u0015"' - FromJson = '' - } - @{ - TestInput = 22 - ToJson = '"\u0016"' - FromJson = '' - } - @{ - TestInput = 23 - ToJson = '"\u0017"' - FromJson = '' - } - @{ - TestInput = 24 - ToJson = '"\u0018"' - FromJson = '' - } - @{ - TestInput = 25 - ToJson = '"\u0019"' - FromJson = '' - } - @{ - TestInput = 26 - ToJson = '"\u001a"' - FromJson = '' - } - @{ - TestInput = 27 - ToJson = '"\u001b"' - FromJson = '' - } - @{ - TestInput = 28 - ToJson = '"\u001c"' - FromJson = '' - } - @{ - TestInput = 29 - ToJson = '"\u001d"' - FromJson = '' - } - @{ - TestInput = 30 - ToJson = '"\u001e"' - FromJson = '' - } - @{ - TestInput = 31 - ToJson = '"\u001f"' - FromJson = '' - } - @{ - TestInput = 32 - ToJson = '" "' - FromJson = ' ' - } - @{ - TestInput = 33 - ToJson = '"!"' - FromJson = '!' - } - @{ - TestInput = 34 - ToJson = '"\""' - FromJson = '"' - } - @{ - TestInput = 35 - ToJson = '"#"' - FromJson = '#' - } - @{ - TestInput = 36 - ToJson = '"$"' - FromJson = '$' - } - @{ - TestInput = 37 - ToJson = '"%"' - FromJson = '%' - } - @{ - TestInput = 38 - ToJson = if ( $IsCore ) { '"&"' } else { '"\u0026"' } - FromJson = '&' - } - @{ - TestInput = 39 - ToJson = if ( $IsCore ) { '"''"' } else { '"\u0027"' } - FromJson = "'" - } - @{ - TestInput = 40 - ToJson = '"("' - FromJson = '(' - } - @{ - TestInput = 41 - ToJson = '")"' - FromJson = ')' - } - @{ - TestInput = 42 - ToJson = '"*"' - FromJson = '*' - } - @{ - TestInput = 43 - ToJson = '"+"' - FromJson = '+' - } - @{ - TestInput = 44 - ToJson = '","' - FromJson = ',' - } - @{ - TestInput = 45 - ToJson = '"-"' - FromJson = '-' - } - @{ - TestInput = 46 - ToJson = '"."' - FromJson = '.' - } - @{ - TestInput = 47 - ToJson = '"/"' - FromJson = '/' - } - @{ - TestInput = 48 - ToJson = '"0"' - FromJson = '0' - } - @{ - TestInput = 49 - ToJson = '"1"' - FromJson = '1' - } - @{ - TestInput = 50 - ToJson = '"2"' - FromJson = '2' - } - @{ - TestInput = 51 - ToJson = '"3"' - FromJson = '3' - } - @{ - TestInput = 52 - ToJson = '"4"' - FromJson = '4' - } - @{ - TestInput = 53 - ToJson = '"5"' - FromJson = '5' - } - @{ - TestInput = 54 - ToJson = '"6"' - FromJson = '6' - } - @{ - TestInput = 55 - ToJson = '"7"' - FromJson = '7' - } - @{ - TestInput = 56 - ToJson = '"8"' - FromJson = '8' - } - @{ - TestInput = 57 - ToJson = '"9"' - FromJson = '9' - } - @{ - TestInput = 58 - ToJson = '":"' - FromJson = ':' - } - @{ - TestInput = 59 - ToJson = '";"' - FromJson = ';' - } - @{ - TestInput = 60 - ToJson = if ( $IsCore ) { '"<"' } else { '"\u003c"' } - FromJson = '<' - } - @{ - TestInput = 61 - ToJson = '"="' - FromJson = '=' - } - @{ - TestInput = 62 - ToJson = if ( $IsCore ) { '">"' } else { '"\u003e"' } - FromJson = '>' - } - @{ - TestInput = 63 - ToJson = '"?"' - FromJson = '?' - } - @{ - TestInput = 64 - ToJson = '"@"' - FromJson = '@' - } - @{ - TestInput = 65 - ToJson = '"A"' - FromJson = 'A' - } - @{ - TestInput = 66 - ToJson = '"B"' - FromJson = 'B' - } - @{ - TestInput = 67 - ToJson = '"C"' - FromJson = 'C' - } - @{ - TestInput = 68 - ToJson = '"D"' - FromJson = 'D' - } - @{ - TestInput = 69 - ToJson = '"E"' - FromJson = 'E' - } - @{ - TestInput = 70 - ToJson = '"F"' - FromJson = 'F' - } - @{ - TestInput = 71 - ToJson = '"G"' - FromJson = 'G' - } - @{ - TestInput = 72 - ToJson = '"H"' - FromJson = 'H' - } - @{ - TestInput = 73 - ToJson = '"I"' - FromJson = 'I' - } - @{ - TestInput = 74 - ToJson = '"J"' - FromJson = 'J' - } - @{ - TestInput = 75 - ToJson = '"K"' - FromJson = 'K' - } - @{ - TestInput = 76 - ToJson = '"L"' - FromJson = 'L' - } - @{ - TestInput = 77 - ToJson = '"M"' - FromJson = 'M' - } - @{ - TestInput = 78 - ToJson = '"N"' - FromJson = 'N' - } - @{ - TestInput = 79 - ToJson = '"O"' - FromJson = 'O' - } - @{ - TestInput = 80 - ToJson = '"P"' - FromJson = 'P' - } - @{ - TestInput = 81 - ToJson = '"Q"' - FromJson = 'Q' - } - @{ - TestInput = 82 - ToJson = '"R"' - FromJson = 'R' - } - @{ - TestInput = 83 - ToJson = '"S"' - FromJson = 'S' - } - @{ - TestInput = 84 - ToJson = '"T"' - FromJson = 'T' - } - @{ - TestInput = 85 - ToJson = '"U"' - FromJson = 'U' - } - @{ - TestInput = 86 - ToJson = '"V"' - FromJson = 'V' - } - @{ - TestInput = 87 - ToJson = '"W"' - FromJson = 'W' - } - @{ - TestInput = 88 - ToJson = '"X"' - FromJson = 'X' - } - @{ - TestInput = 89 - ToJson = '"Y"' - FromJson = 'Y' - } - @{ - TestInput = 90 - ToJson = '"Z"' - FromJson = 'Z' - } - @{ - TestInput = 91 - ToJson = '"["' - FromJson = '[' - } - @{ - TestInput = 92 - ToJson = '"\\"' - FromJson = '\' - } - @{ - TestInput = 93 - ToJson = '"]"' - FromJson = ']' - } - @{ - TestInput = 94 - ToJson = '"^"' - FromJson = '^' - } - @{ - TestInput = 95 - ToJson = '"_"' - FromJson = '_' - } - @{ - TestInput = 96 - ToJson = '"`"' - FromJson = '`' - } - @{ - TestInput = 97 - ToJson = '"a"' - FromJson = 'a' - } - @{ - TestInput = 98 - ToJson = '"b"' - FromJson = 'b' - } - @{ - TestInput = 99 - ToJson = '"c"' - FromJson = 'c' - } - @{ - TestInput = 100 - ToJson = '"d"' - FromJson = 'd' - } - @{ - TestInput = 101 - ToJson = '"e"' - FromJson = 'e' - } - @{ - TestInput = 102 - ToJson = '"f"' - FromJson = 'f' - } - @{ - TestInput = 103 - ToJson = '"g"' - FromJson = 'g' - } - @{ - TestInput = 104 - ToJson = '"h"' - FromJson = 'h' - } - @{ - TestInput = 105 - ToJson = '"i"' - FromJson = 'i' - } - @{ - TestInput = 106 - ToJson = '"j"' - FromJson = 'j' - } - @{ - TestInput = 107 - ToJson = '"k"' - FromJson = 'k' - } - @{ - TestInput = 108 - ToJson = '"l"' - FromJson = 'l' - } - @{ - TestInput = 109 - ToJson = '"m"' - FromJson = 'm' - } - @{ - TestInput = 110 - ToJson = '"n"' - FromJson = 'n' - } - @{ - TestInput = 111 - ToJson = '"o"' - FromJson = 'o' - } - @{ - TestInput = 112 - ToJson = '"p"' - FromJson = 'p' - } - @{ - TestInput = 113 - ToJson = '"q"' - FromJson = 'q' - } - @{ - TestInput = 114 - ToJson = '"r"' - FromJson = 'r' - } - @{ - TestInput = 115 - ToJson = '"s"' - FromJson = 's' - } - @{ - TestInput = 116 - ToJson = '"t"' - FromJson = 't' - } - @{ - TestInput = 117 - ToJson = '"u"' - FromJson = 'u' - } - @{ - TestInput = 118 - ToJson = '"v"' - FromJson = 'v' - } - @{ - TestInput = 119 - ToJson = '"w"' - FromJson = 'w' - } - @{ - TestInput = 120 - ToJson = '"x"' - FromJson = 'x' - } - @{ - TestInput = 121 - ToJson = '"y"' - FromJson = 'y' - } - @{ - TestInput = 122 - ToJson = '"z"' - FromJson = 'z' - } - @{ - TestInput = 123 - ToJson = '"{"' - FromJson = '{' - } - @{ - TestInput = 124 - ToJson = '"|"' - FromJson = '|' - } - @{ - TestInput = 125 - ToJson = '"}"' - FromJson = '}' - } - @{ - TestInput = 126 - ToJson = '"~"' - FromJson = '~' - } - @{ - TestInput = 127 - ToJson = '""' - FromJson = '' - } - ) - - function ValidateJsonSerializationForAsciiValues - { - param ($testCase) - - It "Validate 'ConvertTo-Json ([char]$($testCase.TestInput))', and 'ConvertTo-Json ([char]$($testCase.TestInput)) | ConvertFrom-Json'" { - - $result = @{ - ToJson = ConvertTo-Json ([char]$testCase.TestInput) - FromJson = ConvertTo-Json ([char]$testCase.TestInput) | ConvertFrom-Json - } - - if ($testCase.FromJson) - { - $result.FromJson | Should Be $testCase.FromJson - } - else - { - # There are two char for which the deserialized object must be compare to the serialized one via "Should Match" - # These values are [char]0 and [char]13. - $result.FromJson | Should Match $testCase.FromJson - } - $result.ToJson | Should Be $testCase.ToJson - } - } - - foreach ($testCase in $testCases) - { - ValidateJsonSerializationForAsciiValues $testCase - } - } - - Context "Validate Json serialization for types" { - - $testCases = @( - - ## Decimal types - Decimals are a 128-bit data type - @{ - TestInput = '[decimal]::MinValue' - FromJson = [decimal]::MinValue - ToJson = [decimal]::MinValue - } - @{ - TestInput = '[decimal]::MaxValue' - FromJson = [decimal]::MaxValue - ToJson = [decimal]::MaxValue - } - - # An sbyte is a signed 8-bit integer, and it ranges from -128 to 127. - # A byte is an unsigned 8-bit integer that ranges from 0 to 255 - @{ - TestInput = '[byte]::MinValue' - FromJson = [byte]::MinValue - ToJson = [byte]::MinValue - } - @{ - TestInput = '[byte]::MaxValue' - FromJson = [byte]::MaxValue - ToJson = [byte]::MaxValue - } - @{ - TestInput = '[sbyte]::MinValue' - FromJson = [sbyte]::MinValue - ToJson = [sbyte]::MinValue - } - @{ - TestInput = '[sbyte]::MaxValue' - FromJson = [sbyte]::MaxValue - ToJson = [sbyte]::MaxValue - } - @{ - TestInput = '[char]::MinValue' - FromJson = $null - ToJson = 'null' - } - @{ - TestInput = '[char]::MaxValue - 1' - FromJson = [char]::MaxValue - 1 - ToJson = [char]::MaxValue - 1 - } - @{ - TestInput = '[string]::Empty' - FromJson = [string]::Empty - ToJson = '""' - } - @{ - TestInput = '[string]"hello"' - FromJson = [string]"hello" - ToJson = '"hello"' - } - - # Int, int32, uint32, uint16, int16 - - # 32-bit signed integer - @{ - TestInput = '[int]::MaxValue' - FromJson = [int]::MaxValue - ToJson = [int]::MaxValue - } - @{ - TestInput = '[int]::MinValue' - FromJson = [int]::MinValue - ToJson = [int]::MinValue - } - @{ - TestInput = '[int32]::MaxValue' - FromJson = [int32]::MaxValue - ToJson = [int32]::MaxValue - } - @{ - TestInput = '[int32]::MinValue' - FromJson = [int32]::MinValue - ToJson = [int32]::MinValue - } - - # 32-bit unsigned integer - @{ - TestInput = '[uint32]::MaxValue' - FromJson = [uint32]::MaxValue - ToJson = [uint32]::MaxValue - } - @{ - TestInput = '[uint32]::MinValue' - FromJson = [uint32]::MinValue - ToJson = [uint32]::MinValue - } - - # 16-bit unsigned integer - @{ - TestInput = '[int16]::MinValue' - FromJson = [int16]::MinValue - ToJson = [int16]::MinValue - } - @{ - TestInput = '[uint16]::MaxValue' - FromJson = [uint16]::MaxValue - ToJson = [uint16]::MaxValue - } - - # 64-bit unsigned integer - @{ - TestInput = '[uint64]::MinValue' - FromJson = [uint64]::MinValue - ToJson = [uint64]::MinValue - } - @{ - TestInput = '[uint64]::MinValue' - FromJson = [uint64]::MinValue - ToJson = [uint64]::MinValue - } - - # 64 bit signed integer - @{ - TestInput = '[int64]::MaxValue' - FromJson = [int64]::MaxValue - ToJson = [int64]::MaxValue - } - @{ - TestInput = '[int64]::MinValue' - FromJson = [int64]::MinValue - ToJson = [int64]::MinValue - } - @{ - TestInput = '[long]::MaxValue' - FromJson = [long]::MaxValue - ToJson = [long]::MaxValue - } - @{ - TestInput = '[long]::MinValue' - FromJson = [long]::MinValue - ToJson = [long]::MinValue - } - - # Bool - @{ - TestInput = '[bool](1)' - FromJson = [bool](1) - ToJson = $true - } - @{ - TestInput = '[bool](0)' - FromJson = $false - ToJson = 'False' - } - - # Decimal - @{ - TestInput = '[decimal]::MaxValue' - FromJson = [decimal]::MaxValue - ToJson = [decimal]::MaxValue - } - @{ - TestInput = '[decimal]::MinValue' - FromJson = [decimal]::MinValue - ToJson = [decimal]::MinValue - } - - # Single - @{ - TestInput = '[single]::MaxValue' - FromJson = "3.40282347E+38" - ToJson = "3.40282347E+38" - } - @{ - TestInput = '[single]::MinValue' - FromJson = "-3.40282347E+38" - ToJson = "-3.40282347E+38" - } - - # Double - @{ - TestInput = '[double]::MaxValue' - FromJson = [double]::MaxValue - ToJson = [double]::MaxValue - } - @{ - TestInput = '[double]::MinValue' - FromJson = [double]::MinValue - ToJson = [double]::MinValue - } - ) - - function ValidateJsonSerialization - { - param ($testCase) - - if ( $TestCase.TestInput -eq "[char]::MinValue" ) { $pending = $true } else { $pending = $false } - It "Validate '$($testCase.TestInput) | ConvertTo-Json' and '$($testCase.TestInput) | ConvertTo-Json | ConvertFrom-Json'" -pending:$pending { - - # The test case input is executed via invoke-expression. Then, we use this value as an input to ConvertTo-Json, - # and the result is saved into in the $result.ToJson variable. Lastly, this value is deserialized back using - # ConvertFrom-Json, and the value is saved to $result.FromJson for comparison. - - $expression = Invoke-Expression $testCase.TestInput - $result = @{ - ToJson = $expression | ConvertTo-Json - FromJson = $expression | ConvertTo-Json | ConvertFrom-Json - } - - $result.ToJson | Should Be $testCase.ToJson - $result.FromJson | Should Be $testCase.FromJson - } - } - - foreach ($testCase in $testCases) - { - ValidateJsonSerialization $testCase - } - } - - - Context "Validate Json Serialization for 'Get-CimClass' and 'Get-Command'" { - - function ValidateProperties - { - param ( - $serialized, - $expected, - $properties - ) - - # Validate that the two collections are the same size. - $expected.Count | Should Be $serialized.Count - - for ($index = 0; $index -lt $serialized.Count; $index++) - { - $serializedObject = $serialized[$index] - $expectedObject = $expected[$index] - foreach ($property in $properties) - { - # Write-Verbose "Validating $property" -Verbose - if ($property -eq "Qualifiers") - { - $serializedObject.$property.Count | Should Be $expectedObject.$property.Count - } - else - { - $serializedObject.$property | Should Be $expectedObject.$property - } - } - } - } - - It "Validate that CimClass Properties for win32_bios can be serialized using ConvertTo-Json and ConvertFrom-Json" -skip { - - $class = Get-CimClass win32_bios - - $result = @{ - Expected = $class.CimClassProperties | ForEach-Object {$_} - SerializedViaJson = $class.CimClassProperties | ConvertTo-Json -Depth 10 | ConvertFrom-Json - } - - $propertiesToValidate = @("Name", "Flags", "Qualifiers", "ReferenceClassName") - - ValidateProperties -serialized $result.SerializedViaJson -expected $result.Expected -properties $propertiesToValidate - } - - It "Validate 'Get-Command Get-help' output with Json conversion" { - - $result = @{ - Expected = @(Get-Command Get-help) - SerializedViaJson = @(Get-Command Get-help | ConvertTo-Json | ConvertFrom-Json) - } - - $propertiesToValidate = @("Name", "Noun", "Verb") - ValidateProperties -serialized $result.SerializedViaJson -expected $result.Expected -properties $propertiesToValidate - } - - It "Validate 'Get-Command Get-Help, Get-command, Get-Member' output with Json conversion" { - - $result = @{ - Expected = @(Get-Command Get-Help, Get-Command, Get-Member) - SerializedViaJson = @(Get-Command Get-Help, Get-Command, Get-Member) | ConvertTo-Json | ConvertFrom-Json - } - - $propertiesToValidate = @("Name", "Source", "HelpFile") - ValidateProperties -serialized $result.SerializedViaJson -expected $result.Expected -properties $propertiesToValidate - } - - It "ConvertTo-JSON a dictionary of arrays" { - $a = 1..5 - $b = 6..10 - - $actual = [ordered]@{'a'=$a;'b'=$b} | ConvertTo-Json - $expected = @' -{ - "a": [ - 1, - 2, - 3, - 4, - 5 - ], - "b": [ - 6, - 7, - 8, - 9, - 10 - ] -} -'@ - $actual | Should Be $expected - } - } -} - -Describe "Json Bug fixes" -Tags "Feature" { - - function RunJsonTest - { - param ($testCase) - - It "$($testCase.Name)" { - - # Create a nested object - $start = 1 - $previous = @{ - Depth = $($testCase.NumberOfElements) - Next = $null - } - - ($($testCase.NumberOfElements)-1)..$start | foreach { - $current = @{ - Depth = $_ - Next = $previous - } - $previous = $current - } - - if ($testCase.ShouldThrow) - { - try - { - $previous | ConvertTo-Json -Depth $testCase.MaxDepth - throw "CodeExecuted" - } - catch - { - $_.FullyQualifiedErrorId | Should Be $testCase.FullyQualifiedErrorId - } - } - else - { - $theError = $null - try - { - $previous | ConvertTo-Json -Depth $testCase.MaxDepth | ConvertFrom-Json - } - catch - { - $theError = $_ - } - $theError | Should Be $null - } - } - } - - $testCases = @( - @{ - Name = "ConvertTo-Json -Depth 101 throws MaximumAllowedDepthReached when the user specifies a depth greather than 100." - NumberOfElements = 10 - MaxDepth = 101 - FullyQualifiedErrorId = "ReachedMaximumDepthAllowed,Microsoft.PowerShell.Commands.ConvertToJsonCommand" - ShouldThrow = $true - } - @{ - Name = "ConvertTo-Json and ConvertFrom-Json work for any depth less than or equal to 100." - NumberOfElements = 100 - MaxDepth = 100 - ShouldThrow = $false - } - @{ - Name = "ConvertTo-Json and ConvertFrom-Json work for depth 100 with an object larger than 100." - NumberOfElements = 105 - MaxDepth = 100 - ShouldThrow = $false - } - ) - - foreach ($testCase in $testCases) - { - RunJsonTest $testCase - } -} +# +# Copyright (c) Microsoft Corporation, 2015 +# +# This is a Pester test suite which validate the Json cmdlets. +# + +# +# This 'Describe' is for tests that were converted from utscripts (SDXROOT/admin/monad/tests/monad/DRT/utscripts) +# and C# tests (SDXROOT/admin/monad/tests/monad/DRT/commands/utility/UnitTests) to Pester. +# +Describe "Json Tests" -Tags "Feature" { + + BeforeAll { + + function ValidateSampleObject + { + param ($result, [switch]$hasEmbeddedSampleObject ) + + Write-Verbose "validating deserialized SampleObject" -Verbose + $result.SampleInt | Should Be 98765 + $result.SampleString | Should Match "stringVal" + $result.SampleArray.Count | Should Be 2 + $result.SampleTrue | Should Be $true + $result.SampleFalse | Should Be $false + $result.SampleNull | Should Be $null + $result.SampleFloat | Should Be 9.8765E+43 + + if ($hasEmbeddedSampleObject) + { + Write-Verbose "validating deserialized Embedded SampleObject" -Verbose + ValidateSampleObject -result $result.SampleObject + } + } + + } + + Context "ConvertTo-Json Bug Fixes" { + + It "ConvertTo-JSON should not have hard coded english error message" { + + # Test follow-up for bug WinBlue: 163372 - ConvertTo-JSON has hard coded english error message. + $process = Get-Process -Id $PID + $hash = @{ $process = "def" } + $expectedFullyQualifiedErrorId = "NonStringKeyInDictionary,Microsoft.PowerShell.Commands.ConvertToJsonCommand" + + try + { + ConvertTo-Json -InputObject $hash + throw "CodeExecuted" + } + catch + { + $_.FullyQualifiedErrorId | should be $expectedFullyQualifiedErrorId + } + } + + It "ConvertTo-Json should handle terms with double quotes" { + + # Test follow-up for bug WinBlue: 11484 - ConvertTo-Json can't handle terms with double quotes. + + $notcompressed = ConvertTo-JSON @{ FirstName = 'Hello " World' } + $compressed = ConvertTo-Json @{ FirstName = 'Hello " World' } -Compress + $valueFromNotCompressedResult = ConvertFrom-Json -InputObject $notcompressed + $valueFromCompressedResult = ConvertFrom-Json -InputObject $compressed + + $valueFromNotCompressedResult.FirstName | Should Match $valueFromCompressedResult.FirstName + } + + It "Convertto-Json should handle Enum based on Int64" { + + # Test follow-up for bug Win8: 378368 Convertto-Json problems with Enum based on Int64. + enum TestEnum : ulong { One = 1, Two = 2 } + enum TestEnum1 : long { One = 1, Two = 2 } + enum TestEnum2 : int { One = 1, Two = 2 } + + class Test { + [TestEnum] $TestEnum = [TestEnum]::One + [TestEnum1] $TestEnum1 = [TestEnum1]::Two + [TestEnum2] $TestEnum2 = [TestEnum2]::One + } + $op = [Test]::New() | convertto-json | convertfrom-json + $op.TestEnum | Should Be "One" + $op.TestEnum1 | Should Be "Two" + $op.TestEnum2 | Should Be 1 + } + + It "Test followup for Windows 8 bug 121627" { + + $JsonString = Get-Command Get-help |Select-Object Name, Noun, Verb| ConvertTo-Json + $actual = ConvertFrom-Json $JsonString + + $actual.Name | Should Be "Get-Help" + $actual.Noun | Should Be "Help" + $actual.Verb | Should Be "Get" + } + } + + Context "ConvertFrom and ConvertTo on JsonObject Tests" { + + It "Convert dictionary to PSObject" { + + $response = ConvertFrom-Json '{"d":{"__type":"SimpleJsonObject","Name":{"First":"Joel","Last":"Wood"},"Greeting":"Hello"}}' + $response.d.Name.First | Should Match "Joel" + } + + It "Convert to Json using PSObject" -pending:($IsCore) { + + $response = ConvertFrom-Json '{"d":{"__type":"SimpleJsonObject","Name":{"First":"Joel","Last":"Wood"},"Greeting":"Hello"}}' + + $response2 = ConvertTo-Json -InputObject $response -ErrorAction Continue + $response2 = ConvertTo-Json -InputObject $response -ErrorAction Inquire + $response2 = ConvertTo-Json -InputObject $response -ErrorAction SilentlyContinue + $response2 = ConvertTo-Json -InputObject $response -Depth 2 -Compress + $response2 | Should Be '{"d":{"Name":{"First":"Joel","Last":"Wood"},"Greeting":"Hello"}}' + + $response2 = ConvertTo-Json -InputObject $response -Depth 1 -Compress + $nameString = [System.Management.Automation.LanguagePrimitives]::ConvertTo($response.d.Name, [string]) + $response2 | Should Be "{`"d`":{`"Name`":`"$nameString`",`"Greeting`":`"Hello`"}}" + + $result1 = @" +{ + "d": { + "Name": { + "First": "Joel", + "Last": "Wood" + }, + "Greeting": "Hello" + } +} +"@ + $response2 = ConvertTo-Json -InputObject $response -Depth 2 + $response2 | Should Match $result1 + + $result2 = @" +{ + "d": { + "Name": "$nameString", + "Greeting": "Hello" + } +} +"@ + $response2 = ConvertTo-Json -InputObject $response -Depth 1 + $response2 | Should Match $result2 + + $arraylist = new-Object System.Collections.ArrayList + [void]$arraylist.Add("one") + [void]$arraylist.Add("two") + [void]$arraylist.Add("three") + $response2 = ConvertTo-Json -InputObject $arraylist -Compress + $response2 | Should Be '["one","two","three"]' + + $result3 = @" +[ + "one", + "two", + "three" +] +"@ + $response2 = ConvertTo-Json -InputObject $arraylist + $response2 | Should Be $result3 + + $response2 = $arraylist | ConvertTo-Json + $response2 | Should Be $result3 + } + + It "Convert to Json using hashtable" -pending:($IsCore) { + + $nameHash = @{First="Joe1";Last="Wood"} + $dHash = @{Name=$nameHash; Greeting="Hello"} + $rootHash = @{d=$dHash} + $response3 = ConvertTo-Json -InputObject $rootHash -Depth 2 -Compress + $response3 | Should Be '{"d":{"Greeting":"Hello","Name":{"Last":"Wood","First":"Joe1"}}}' + + $response3 = ConvertTo-Json -InputObject $rootHash -Depth 1 -Compress + $response3 | Should Be '{"d":{"Greeting":"Hello","Name":"System.Collections.Hashtable"}}' + + $result4 = @" +{ + "d": { + "Greeting": "Hello", + "Name": { + "Last": "Wood", + "First": "Joe1" + } + } +} +"@ + $response3 = ConvertTo-Json -InputObject $rootHash -Depth 2 + $response3 | Should Be $result4 + + $result5 = @" +{ + "d": { + "Greeting": "Hello", + "Name": "System.Collections.Hashtable" + } +} +"@ + $response3 = ConvertTo-Json -InputObject $rootHash -Depth 1 + $response3 | Should Be $result5 + } + + It "Convert from Json allows an empty string" { + + $emptyStringResult = ConvertFrom-Json "" + $emptyStringResult | Should Be $null + } + } + + Context "JsonObject Tests" { + + It "AddMember on JsonObject" { + + # create a Version object + $versionObject = New-Object System.Version 2, 3, 4, 14 + + # add a NoteProperty member called Note with a text note + $versionObject | Add-Member -MemberType NoteProperty -Name Note -Value "a version object" + + # add an AliasProperty called Rev as an alias to the Revison property + $versionObject | Add-Member -MemberType AliasProperty -Name Rev -Value Revision + + # add a ScriptProperty called IsOld which returns whether the version is an older version + $versionObject | Add-Member -MemberType ScriptProperty -Name IsOld -Value { ($this.Major -le 3) } + + $jstr = ConvertTo-Json $versionObject + + # convert the JSON string to a JSON object + $json = ConvertFrom-Json $jstr + + # Check the basic properties + $json.Major | Should Be 2 + $json.Minor | Should Be 3 + $json.Build | Should Be 4 + $json.Revision | Should Be 14 + $json.Note | Should Match "a version object" + + # Check the AliasProperty + $json.Rev | Should Be $json.Revision + + # Check the ScriptProperty + $json.IsOld | Should Be $true + } + + It "ConvertFrom-Json with a key value pair" { + + $json = "{name:1}" + $result = ConvertFrom-Json $json + $result.name | Should Be 1 + } + + It "ConvertFrom-Json with a simple array" { + + $json = "[1,2,3,4,5,6]" + $result = ConvertFrom-Json $json + $result.Count | Should Be 6 + $result.GetType().BaseType.fullname | Should Be "System.Array" + } + + It "ConvertFrom-Json with a float value" { + + $json = '{"SampleFloat1":1.2345E67, "SampleFloat2":-7.6543E-12}' + $result = ConvertFrom-Json $json + + $sampleFloat1 = Invoke-Expression 1.2345E67 + $result.SampleFloat1 | Should Be $sampleFloat1 + + $sampleFloat2 = Invoke-Expression -7.6543E-12 + $result.SampleFloat2 | Should Be $sampleFloat2 + } + + It "ConvertFrom-Json hash table nested in array" { + + $json = "['one', 'two', {'First':1,'Second':2,'Third':['Five','Six', 'Seven']}, 'four']" + $result = ConvertFrom-Json $json + + $result.Count | Should Be 4 + $result[0] | Should Be "one" + $result[1] | Should Be "two" + $result[3] | Should Be "four" + + $hash = $result[2] + $hash.First | Should Be 1 + $hash.Second | Should Be 2 + $hash.Third.Count | Should Be 3 + $hash.Third[0] | Should Be "Five" + $hash.Third[1] | Should Be "Six" + $hash.Third[2] | Should Be "Seven" + } + + It "ConvertFrom-Json array nested in hash table" { + + $json = '{"First":["one", "two", "three"], "Second":["four", "five"], "Third": {"blah": 4}}' + $result = ConvertFrom-Json $json + + $result.First.Count | Should Be 3 + $result.First[0] | Should Be "one" + $result.First[1] | Should Be "two" + $result.First[2] | Should Be "three" + + $result.Second.Count | Should Be 2 + $result.Second[0] | Should Be "four" + $result.Second[1] | Should Be "five" + + $result.Third.blah | Should Be "4" + } + + It "ConvertFrom-Json case insensitive test" { + + $json = '{"sAMPleValUE":12345}' + $result = ConvertFrom-Json $json + + $result.SampleValue | Should Be 12345 + } + + + It "ConvertFrom-Json sample values" { + + $json = '{"SampleInt":98765, "SampleString":"stringVal","SampleArray":[2,"two"], "SampleTrue":true, "SampleFalse":false,"SampleNull":null, "SampleFloat":9.8765E43}' + $result = ConvertFrom-Json $json + + # Validate the result object + ValidateSampleObject -result $result + + + $json = '{"SampleInt":98765, "SampleString":"stringVal","SampleArray":[2,"two"], "SampleTrue":true, ' + + '"SampleFalse":false,"SampleNull":null, "SampleFloat":9.8765E43, "SampleObject":'+ + '{"SampleInt":98765, "SampleString":"stringVal","SampleArray":[2,"two"], '+ + '"SampleTrue":true, "SampleFalse":false,"SampleNull":null, "SampleFloat":9.8765E43}}' + + # Validate the result object + $result = ConvertFrom-Json $json + ValidateSampleObject -result $result -hasEmbeddedSampleObject + } + + It "ConvertFrom-Json with special characters" { + + $json = '{"SampleValue":"\"\\\b\f\n\r\t\u4321\uD7FF"}' + $result = ConvertFrom-Json $json + $result.SampleValue[0] | Should Be '"' + $result.SampleValue[1] | Should Be '\' + $result.SampleValue[2] | Should Be 0x8 + $result.SampleValue[3] | Should Be 0xC + $result.SampleValue[4] | Should Be 0xA + $result.SampleValue[5] | Should Be 0xD + $result.SampleValue[6] | Should Be 0x9 + $result.SampleValue[7] | Should Be 0x4321 + $result.SampleValue[8] | Should Be 0xD7FF + } + } +} + +# This Describe is for new Json tests +# +Describe "Validate Json serialization" -Tags "CI" { + + Context "Validate Json serialization ascii values" { + + $testCases = @( + @{ + TestInput = 0 + ToJson = if ( $IsCore ) { '"\u0000"' } else { 'null' } + FromJson = '' + } + @{ + TestInput = 1 + ToJson = '"\u0001"' + FromJson = '' + } + @{ + TestInput = 2 + ToJson = '"\u0002"' + FromJson = '' + } + @{ + TestInput = 3 + ToJson = '"\u0003"' + FromJson = '' + } + @{ + TestInput = 4 + ToJson = '"\u0004"' + FromJson = '' + } + @{ + TestInput = 5 + ToJson = '"\u0005"' + FromJson = '' + } + @{ + TestInput = 6 + ToJson = '"\u0006"' + FromJson = '' + } + @{ + TestInput = 7 + ToJson = '"\u0007"' + FromJson = '' + } + @{ + TestInput = 8 + ToJson = '"\b"' + FromJson = '' + } + @{ + TestInput = 9 + ToJson = '"\t"' + FromJson = ' ' + } + @{ + TestInput = 10 + ToJson = '"\n"' + FromJson = "`n" + } + @{ + TestInput = 11 + ToJson = '"\u000b"' + FromJson = ' ' + } + @{ + TestInput = 12 + ToJson = '"\f"' + FromJson = ' ' + } + @{ + TestInput = 13 + ToJson = '"\r"' + FromJson = '' + } + @{ + TestInput = 14 + ToJson = '"\u000e"' + FromJson = '' + } + @{ + TestInput = 15 + ToJson = '"\u000f"' + FromJson = '' + } + @{ + TestInput = 16 + ToJson = '"\u0010"' + FromJson = '' + } + @{ + TestInput = 17 + ToJson = '"\u0011"' + FromJson = '' + } + @{ + TestInput = 18 + ToJson = '"\u0012"' + FromJson = '' + } + @{ + TestInput = 19 + ToJson = '"\u0013"' + FromJson = '' + } + @{ + TestInput = 20 + ToJson = '"\u0014"' + FromJson = '' + } + @{ + TestInput = 21 + ToJson = '"\u0015"' + FromJson = '' + } + @{ + TestInput = 22 + ToJson = '"\u0016"' + FromJson = '' + } + @{ + TestInput = 23 + ToJson = '"\u0017"' + FromJson = '' + } + @{ + TestInput = 24 + ToJson = '"\u0018"' + FromJson = '' + } + @{ + TestInput = 25 + ToJson = '"\u0019"' + FromJson = '' + } + @{ + TestInput = 26 + ToJson = '"\u001a"' + FromJson = '' + } + @{ + TestInput = 27 + ToJson = '"\u001b"' + FromJson = '' + } + @{ + TestInput = 28 + ToJson = '"\u001c"' + FromJson = '' + } + @{ + TestInput = 29 + ToJson = '"\u001d"' + FromJson = '' + } + @{ + TestInput = 30 + ToJson = '"\u001e"' + FromJson = '' + } + @{ + TestInput = 31 + ToJson = '"\u001f"' + FromJson = '' + } + @{ + TestInput = 32 + ToJson = '" "' + FromJson = ' ' + } + @{ + TestInput = 33 + ToJson = '"!"' + FromJson = '!' + } + @{ + TestInput = 34 + ToJson = '"\""' + FromJson = '"' + } + @{ + TestInput = 35 + ToJson = '"#"' + FromJson = '#' + } + @{ + TestInput = 36 + ToJson = '"$"' + FromJson = '$' + } + @{ + TestInput = 37 + ToJson = '"%"' + FromJson = '%' + } + @{ + TestInput = 38 + ToJson = if ( $IsCore ) { '"&"' } else { '"\u0026"' } + FromJson = '&' + } + @{ + TestInput = 39 + ToJson = if ( $IsCore ) { '"''"' } else { '"\u0027"' } + FromJson = "'" + } + @{ + TestInput = 40 + ToJson = '"("' + FromJson = '(' + } + @{ + TestInput = 41 + ToJson = '")"' + FromJson = ')' + } + @{ + TestInput = 42 + ToJson = '"*"' + FromJson = '*' + } + @{ + TestInput = 43 + ToJson = '"+"' + FromJson = '+' + } + @{ + TestInput = 44 + ToJson = '","' + FromJson = ',' + } + @{ + TestInput = 45 + ToJson = '"-"' + FromJson = '-' + } + @{ + TestInput = 46 + ToJson = '"."' + FromJson = '.' + } + @{ + TestInput = 47 + ToJson = '"/"' + FromJson = '/' + } + @{ + TestInput = 48 + ToJson = '"0"' + FromJson = '0' + } + @{ + TestInput = 49 + ToJson = '"1"' + FromJson = '1' + } + @{ + TestInput = 50 + ToJson = '"2"' + FromJson = '2' + } + @{ + TestInput = 51 + ToJson = '"3"' + FromJson = '3' + } + @{ + TestInput = 52 + ToJson = '"4"' + FromJson = '4' + } + @{ + TestInput = 53 + ToJson = '"5"' + FromJson = '5' + } + @{ + TestInput = 54 + ToJson = '"6"' + FromJson = '6' + } + @{ + TestInput = 55 + ToJson = '"7"' + FromJson = '7' + } + @{ + TestInput = 56 + ToJson = '"8"' + FromJson = '8' + } + @{ + TestInput = 57 + ToJson = '"9"' + FromJson = '9' + } + @{ + TestInput = 58 + ToJson = '":"' + FromJson = ':' + } + @{ + TestInput = 59 + ToJson = '";"' + FromJson = ';' + } + @{ + TestInput = 60 + ToJson = if ( $IsCore ) { '"<"' } else { '"\u003c"' } + FromJson = '<' + } + @{ + TestInput = 61 + ToJson = '"="' + FromJson = '=' + } + @{ + TestInput = 62 + ToJson = if ( $IsCore ) { '">"' } else { '"\u003e"' } + FromJson = '>' + } + @{ + TestInput = 63 + ToJson = '"?"' + FromJson = '?' + } + @{ + TestInput = 64 + ToJson = '"@"' + FromJson = '@' + } + @{ + TestInput = 65 + ToJson = '"A"' + FromJson = 'A' + } + @{ + TestInput = 66 + ToJson = '"B"' + FromJson = 'B' + } + @{ + TestInput = 67 + ToJson = '"C"' + FromJson = 'C' + } + @{ + TestInput = 68 + ToJson = '"D"' + FromJson = 'D' + } + @{ + TestInput = 69 + ToJson = '"E"' + FromJson = 'E' + } + @{ + TestInput = 70 + ToJson = '"F"' + FromJson = 'F' + } + @{ + TestInput = 71 + ToJson = '"G"' + FromJson = 'G' + } + @{ + TestInput = 72 + ToJson = '"H"' + FromJson = 'H' + } + @{ + TestInput = 73 + ToJson = '"I"' + FromJson = 'I' + } + @{ + TestInput = 74 + ToJson = '"J"' + FromJson = 'J' + } + @{ + TestInput = 75 + ToJson = '"K"' + FromJson = 'K' + } + @{ + TestInput = 76 + ToJson = '"L"' + FromJson = 'L' + } + @{ + TestInput = 77 + ToJson = '"M"' + FromJson = 'M' + } + @{ + TestInput = 78 + ToJson = '"N"' + FromJson = 'N' + } + @{ + TestInput = 79 + ToJson = '"O"' + FromJson = 'O' + } + @{ + TestInput = 80 + ToJson = '"P"' + FromJson = 'P' + } + @{ + TestInput = 81 + ToJson = '"Q"' + FromJson = 'Q' + } + @{ + TestInput = 82 + ToJson = '"R"' + FromJson = 'R' + } + @{ + TestInput = 83 + ToJson = '"S"' + FromJson = 'S' + } + @{ + TestInput = 84 + ToJson = '"T"' + FromJson = 'T' + } + @{ + TestInput = 85 + ToJson = '"U"' + FromJson = 'U' + } + @{ + TestInput = 86 + ToJson = '"V"' + FromJson = 'V' + } + @{ + TestInput = 87 + ToJson = '"W"' + FromJson = 'W' + } + @{ + TestInput = 88 + ToJson = '"X"' + FromJson = 'X' + } + @{ + TestInput = 89 + ToJson = '"Y"' + FromJson = 'Y' + } + @{ + TestInput = 90 + ToJson = '"Z"' + FromJson = 'Z' + } + @{ + TestInput = 91 + ToJson = '"["' + FromJson = '[' + } + @{ + TestInput = 92 + ToJson = '"\\"' + FromJson = '\' + } + @{ + TestInput = 93 + ToJson = '"]"' + FromJson = ']' + } + @{ + TestInput = 94 + ToJson = '"^"' + FromJson = '^' + } + @{ + TestInput = 95 + ToJson = '"_"' + FromJson = '_' + } + @{ + TestInput = 96 + ToJson = '"`"' + FromJson = '`' + } + @{ + TestInput = 97 + ToJson = '"a"' + FromJson = 'a' + } + @{ + TestInput = 98 + ToJson = '"b"' + FromJson = 'b' + } + @{ + TestInput = 99 + ToJson = '"c"' + FromJson = 'c' + } + @{ + TestInput = 100 + ToJson = '"d"' + FromJson = 'd' + } + @{ + TestInput = 101 + ToJson = '"e"' + FromJson = 'e' + } + @{ + TestInput = 102 + ToJson = '"f"' + FromJson = 'f' + } + @{ + TestInput = 103 + ToJson = '"g"' + FromJson = 'g' + } + @{ + TestInput = 104 + ToJson = '"h"' + FromJson = 'h' + } + @{ + TestInput = 105 + ToJson = '"i"' + FromJson = 'i' + } + @{ + TestInput = 106 + ToJson = '"j"' + FromJson = 'j' + } + @{ + TestInput = 107 + ToJson = '"k"' + FromJson = 'k' + } + @{ + TestInput = 108 + ToJson = '"l"' + FromJson = 'l' + } + @{ + TestInput = 109 + ToJson = '"m"' + FromJson = 'm' + } + @{ + TestInput = 110 + ToJson = '"n"' + FromJson = 'n' + } + @{ + TestInput = 111 + ToJson = '"o"' + FromJson = 'o' + } + @{ + TestInput = 112 + ToJson = '"p"' + FromJson = 'p' + } + @{ + TestInput = 113 + ToJson = '"q"' + FromJson = 'q' + } + @{ + TestInput = 114 + ToJson = '"r"' + FromJson = 'r' + } + @{ + TestInput = 115 + ToJson = '"s"' + FromJson = 's' + } + @{ + TestInput = 116 + ToJson = '"t"' + FromJson = 't' + } + @{ + TestInput = 117 + ToJson = '"u"' + FromJson = 'u' + } + @{ + TestInput = 118 + ToJson = '"v"' + FromJson = 'v' + } + @{ + TestInput = 119 + ToJson = '"w"' + FromJson = 'w' + } + @{ + TestInput = 120 + ToJson = '"x"' + FromJson = 'x' + } + @{ + TestInput = 121 + ToJson = '"y"' + FromJson = 'y' + } + @{ + TestInput = 122 + ToJson = '"z"' + FromJson = 'z' + } + @{ + TestInput = 123 + ToJson = '"{"' + FromJson = '{' + } + @{ + TestInput = 124 + ToJson = '"|"' + FromJson = '|' + } + @{ + TestInput = 125 + ToJson = '"}"' + FromJson = '}' + } + @{ + TestInput = 126 + ToJson = '"~"' + FromJson = '~' + } + @{ + TestInput = 127 + ToJson = '""' + FromJson = '' + } + ) + + function ValidateJsonSerializationForAsciiValues + { + param ($testCase) + + It "Validate 'ConvertTo-Json ([char]$($testCase.TestInput))', and 'ConvertTo-Json ([char]$($testCase.TestInput)) | ConvertFrom-Json'" { + + $result = @{ + ToJson = ConvertTo-Json ([char]$testCase.TestInput) + FromJson = ConvertTo-Json ([char]$testCase.TestInput) | ConvertFrom-Json + } + + if ($testCase.FromJson) + { + $result.FromJson | Should Be $testCase.FromJson + } + else + { + # There are two char for which the deserialized object must be compare to the serialized one via "Should Match" + # These values are [char]0 and [char]13. + $result.FromJson | Should Match $testCase.FromJson + } + $result.ToJson | Should Be $testCase.ToJson + } + } + + foreach ($testCase in $testCases) + { + ValidateJsonSerializationForAsciiValues $testCase + } + } + + Context "Validate Json serialization for types" { + + $testCases = @( + + ## Decimal types - Decimals are a 128-bit data type + @{ + TestInput = '[decimal]::MinValue' + FromJson = [decimal]::MinValue + ToJson = [decimal]::MinValue + } + @{ + TestInput = '[decimal]::MaxValue' + FromJson = [decimal]::MaxValue + ToJson = [decimal]::MaxValue + } + + # An sbyte is a signed 8-bit integer, and it ranges from -128 to 127. + # A byte is an unsigned 8-bit integer that ranges from 0 to 255 + @{ + TestInput = '[byte]::MinValue' + FromJson = [byte]::MinValue + ToJson = [byte]::MinValue + } + @{ + TestInput = '[byte]::MaxValue' + FromJson = [byte]::MaxValue + ToJson = [byte]::MaxValue + } + @{ + TestInput = '[sbyte]::MinValue' + FromJson = [sbyte]::MinValue + ToJson = [sbyte]::MinValue + } + @{ + TestInput = '[sbyte]::MaxValue' + FromJson = [sbyte]::MaxValue + ToJson = [sbyte]::MaxValue + } + @{ + TestInput = '[char]::MinValue' + FromJson = $null + ToJson = 'null' + } + @{ + TestInput = '[char]::MaxValue - 1' + FromJson = [char]::MaxValue - 1 + ToJson = [char]::MaxValue - 1 + } + @{ + TestInput = '[string]::Empty' + FromJson = [string]::Empty + ToJson = '""' + } + @{ + TestInput = '[string]"hello"' + FromJson = [string]"hello" + ToJson = '"hello"' + } + + # Int, int32, uint32, uint16, int16 + + # 32-bit signed integer + @{ + TestInput = '[int]::MaxValue' + FromJson = [int]::MaxValue + ToJson = [int]::MaxValue + } + @{ + TestInput = '[int]::MinValue' + FromJson = [int]::MinValue + ToJson = [int]::MinValue + } + @{ + TestInput = '[int32]::MaxValue' + FromJson = [int32]::MaxValue + ToJson = [int32]::MaxValue + } + @{ + TestInput = '[int32]::MinValue' + FromJson = [int32]::MinValue + ToJson = [int32]::MinValue + } + + # 32-bit unsigned integer + @{ + TestInput = '[uint32]::MaxValue' + FromJson = [uint32]::MaxValue + ToJson = [uint32]::MaxValue + } + @{ + TestInput = '[uint32]::MinValue' + FromJson = [uint32]::MinValue + ToJson = [uint32]::MinValue + } + + # 16-bit unsigned integer + @{ + TestInput = '[int16]::MinValue' + FromJson = [int16]::MinValue + ToJson = [int16]::MinValue + } + @{ + TestInput = '[uint16]::MaxValue' + FromJson = [uint16]::MaxValue + ToJson = [uint16]::MaxValue + } + + # 64-bit unsigned integer + @{ + TestInput = '[uint64]::MinValue' + FromJson = [uint64]::MinValue + ToJson = [uint64]::MinValue + } + @{ + TestInput = '[uint64]::MinValue' + FromJson = [uint64]::MinValue + ToJson = [uint64]::MinValue + } + + # 64 bit signed integer + @{ + TestInput = '[int64]::MaxValue' + FromJson = [int64]::MaxValue + ToJson = [int64]::MaxValue + } + @{ + TestInput = '[int64]::MinValue' + FromJson = [int64]::MinValue + ToJson = [int64]::MinValue + } + @{ + TestInput = '[long]::MaxValue' + FromJson = [long]::MaxValue + ToJson = [long]::MaxValue + } + @{ + TestInput = '[long]::MinValue' + FromJson = [long]::MinValue + ToJson = [long]::MinValue + } + + # Bool + @{ + TestInput = '[bool](1)' + FromJson = [bool](1) + ToJson = $true + } + @{ + TestInput = '[bool](0)' + FromJson = $false + ToJson = 'False' + } + + # Decimal + @{ + TestInput = '[decimal]::MaxValue' + FromJson = [decimal]::MaxValue + ToJson = [decimal]::MaxValue + } + @{ + TestInput = '[decimal]::MinValue' + FromJson = [decimal]::MinValue + ToJson = [decimal]::MinValue + } + + # Single + @{ + TestInput = '[single]::MaxValue' + FromJson = "3.40282347E+38" + ToJson = "3.40282347E+38" + } + @{ + TestInput = '[single]::MinValue' + FromJson = "-3.40282347E+38" + ToJson = "-3.40282347E+38" + } + + # Double + @{ + TestInput = '[double]::MaxValue' + FromJson = [double]::MaxValue + ToJson = [double]::MaxValue + } + @{ + TestInput = '[double]::MinValue' + FromJson = [double]::MinValue + ToJson = [double]::MinValue + } + ) + + function ValidateJsonSerialization + { + param ($testCase) + + if ( $TestCase.TestInput -eq "[char]::MinValue" ) { $pending = $true } else { $pending = $false } + It "Validate '$($testCase.TestInput) | ConvertTo-Json' and '$($testCase.TestInput) | ConvertTo-Json | ConvertFrom-Json'" -pending:$pending { + + # The test case input is executed via invoke-expression. Then, we use this value as an input to ConvertTo-Json, + # and the result is saved into in the $result.ToJson variable. Lastly, this value is deserialized back using + # ConvertFrom-Json, and the value is saved to $result.FromJson for comparison. + + $expression = Invoke-Expression $testCase.TestInput + $result = @{ + ToJson = $expression | ConvertTo-Json + FromJson = $expression | ConvertTo-Json | ConvertFrom-Json + } + + $result.ToJson | Should Be $testCase.ToJson + $result.FromJson | Should Be $testCase.FromJson + } + } + + foreach ($testCase in $testCases) + { + ValidateJsonSerialization $testCase + } + } + + + Context "Validate Json Serialization for 'Get-CimClass' and 'Get-Command'" { + + function ValidateProperties + { + param ( + $serialized, + $expected, + $properties + ) + + # Validate that the two collections are the same size. + $expected.Count | Should Be $serialized.Count + + for ($index = 0; $index -lt $serialized.Count; $index++) + { + $serializedObject = $serialized[$index] + $expectedObject = $expected[$index] + foreach ($property in $properties) + { + # Write-Verbose "Validating $property" -Verbose + if ($property -eq "Qualifiers") + { + $serializedObject.$property.Count | Should Be $expectedObject.$property.Count + } + else + { + $serializedObject.$property | Should Be $expectedObject.$property + } + } + } + } + + It "Validate that CimClass Properties for win32_bios can be serialized using ConvertTo-Json and ConvertFrom-Json" -skip { + + $class = Get-CimClass win32_bios + + $result = @{ + Expected = $class.CimClassProperties | ForEach-Object {$_} + SerializedViaJson = $class.CimClassProperties | ConvertTo-Json -Depth 10 | ConvertFrom-Json + } + + $propertiesToValidate = @("Name", "Flags", "Qualifiers", "ReferenceClassName") + + ValidateProperties -serialized $result.SerializedViaJson -expected $result.Expected -properties $propertiesToValidate + } + + It "Validate 'Get-Command Get-help' output with Json conversion" { + + $result = @{ + Expected = @(Get-Command Get-help) + SerializedViaJson = @(Get-Command Get-help | ConvertTo-Json | ConvertFrom-Json) + } + + $propertiesToValidate = @("Name", "Noun", "Verb") + ValidateProperties -serialized $result.SerializedViaJson -expected $result.Expected -properties $propertiesToValidate + } + + It "Validate 'Get-Command Get-Help, Get-command, Get-Member' output with Json conversion" { + + $result = @{ + Expected = @(Get-Command Get-Help, Get-Command, Get-Member) + SerializedViaJson = @(Get-Command Get-Help, Get-Command, Get-Member) | ConvertTo-Json | ConvertFrom-Json + } + + $propertiesToValidate = @("Name", "Source", "HelpFile") + ValidateProperties -serialized $result.SerializedViaJson -expected $result.Expected -properties $propertiesToValidate + } + + It "ConvertTo-JSON a dictionary of arrays" { + $a = 1..5 + $b = 6..10 + + $actual = [ordered]@{'a'=$a;'b'=$b} | ConvertTo-Json + $expected = @' +{ + "a": [ + 1, + 2, + 3, + 4, + 5 + ], + "b": [ + 6, + 7, + 8, + 9, + 10 + ] +} +'@ + $actual | Should Be $expected + } + } +} + +Describe "Json Bug fixes" -Tags "Feature" { + + function RunJsonTest + { + param ($testCase) + + It "$($testCase.Name)" { + + # Create a nested object + $start = 1 + $previous = @{ + Depth = $($testCase.NumberOfElements) + Next = $null + } + + ($($testCase.NumberOfElements)-1)..$start | foreach { + $current = @{ + Depth = $_ + Next = $previous + } + $previous = $current + } + + if ($testCase.ShouldThrow) + { + try + { + $previous | ConvertTo-Json -Depth $testCase.MaxDepth + throw "CodeExecuted" + } + catch + { + $_.FullyQualifiedErrorId | Should Be $testCase.FullyQualifiedErrorId + } + } + else + { + $theError = $null + try + { + $previous | ConvertTo-Json -Depth $testCase.MaxDepth | ConvertFrom-Json + } + catch + { + $theError = $_ + } + $theError | Should Be $null + } + } + } + + $testCases = @( + @{ + Name = "ConvertTo-Json -Depth 101 throws MaximumAllowedDepthReached when the user specifies a depth greather than 100." + NumberOfElements = 10 + MaxDepth = 101 + FullyQualifiedErrorId = "ReachedMaximumDepthAllowed,Microsoft.PowerShell.Commands.ConvertToJsonCommand" + ShouldThrow = $true + } + @{ + Name = "ConvertTo-Json and ConvertFrom-Json work for any depth less than or equal to 100." + NumberOfElements = 100 + MaxDepth = 100 + ShouldThrow = $false + } + @{ + Name = "ConvertTo-Json and ConvertFrom-Json work for depth 100 with an object larger than 100." + NumberOfElements = 105 + MaxDepth = 100 + ShouldThrow = $false + } + ) + + foreach ($testCase in $testCases) + { + RunJsonTest $testCase + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/PowerShellData.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/PowerShellData.tests.ps1 index f26a7e4c8e..5bdb795377 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/PowerShellData.tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/PowerShellData.tests.ps1 @@ -1,86 +1,86 @@ -Describe "Tests for the Import-PowerShellDataFile cmdlet" -Tags "Feature" { - - It "Validates error on a missing path" { - - $foundError = "" - try - { - Import-PowerShellDataFile -Path /SomeMissingDirectory -ErrorAction Stop - } - catch - { - $foundError = $_.FullyQualifiedErrorId - } - - $foundError | Should be "PathNotFound,Microsoft.PowerShell.Commands.ResolvePathCommand" - } - - It "Validates error on a directory" { - - $foundError = "" - try - { - Import-PowerShellDataFile ${TESTDRIVE} -ErrorAction Stop - } - catch - { - $foundError = $_.FullyQualifiedErrorId - } - - $foundError | Should be "CouldNotParseAsPowerShellDataFile,Import-PowerShellDataFile" - } - - It "Generates a good error on an insecure file" { - - $path = New-TemporaryFile - Set-Content $path '@{ Foo = Get-Process }' - - $foundError = "" - try - { - Import-PowerShellDataFile $path -ErrorAction Stop - } - catch - { - $foundError = $_.FullyQualifiedErrorId - } - finally - { - Remove-Item $path - } - - $foundError | Should be "InvalidOperationException,Import-PowerShellDataFile" - } - - It "Generates a good error on a file that isn't a PowerShell Data File (missing the hashtable root)" { - - $path = New-TemporaryFile - Set-Content $path '"Hello World"' - - $foundError = "" - try - { - Import-PowerShellDataFile $path -ErrorAction Stop - } - catch - { - $foundError = $_.FullyQualifiedErrorId - } - finally - { - Remove-Item $path - } - - $foundError | Should be "CouldNotParseAsPowerShellDataFileNoHashtableRoot,Import-PowerShellDataFile" - } - - It "Can parse a PowerShell Data File (detailed tests are in AST.SafeGetValue tests)" { - - $path = New-TemporaryFile - Set-Content $path '@{ "Hello" = "World" }' - - $result = Import-PowerShellDataFile $path -ErrorAction Stop - $result.Hello | Should be "World" - } - -} +Describe "Tests for the Import-PowerShellDataFile cmdlet" -Tags "Feature" { + + It "Validates error on a missing path" { + + $foundError = "" + try + { + Import-PowerShellDataFile -Path /SomeMissingDirectory -ErrorAction Stop + } + catch + { + $foundError = $_.FullyQualifiedErrorId + } + + $foundError | Should be "PathNotFound,Microsoft.PowerShell.Commands.ResolvePathCommand" + } + + It "Validates error on a directory" { + + $foundError = "" + try + { + Import-PowerShellDataFile ${TESTDRIVE} -ErrorAction Stop + } + catch + { + $foundError = $_.FullyQualifiedErrorId + } + + $foundError | Should be "CouldNotParseAsPowerShellDataFile,Import-PowerShellDataFile" + } + + It "Generates a good error on an insecure file" { + + $path = New-TemporaryFile + Set-Content $path '@{ Foo = Get-Process }' + + $foundError = "" + try + { + Import-PowerShellDataFile $path -ErrorAction Stop + } + catch + { + $foundError = $_.FullyQualifiedErrorId + } + finally + { + Remove-Item $path + } + + $foundError | Should be "InvalidOperationException,Import-PowerShellDataFile" + } + + It "Generates a good error on a file that isn't a PowerShell Data File (missing the hashtable root)" { + + $path = New-TemporaryFile + Set-Content $path '"Hello World"' + + $foundError = "" + try + { + Import-PowerShellDataFile $path -ErrorAction Stop + } + catch + { + $foundError = $_.FullyQualifiedErrorId + } + finally + { + Remove-Item $path + } + + $foundError | Should be "CouldNotParseAsPowerShellDataFileNoHashtableRoot,Import-PowerShellDataFile" + } + + It "Can parse a PowerShell Data File (detailed tests are in AST.SafeGetValue tests)" { + + $path = New-TemporaryFile + Set-Content $path '@{ "Hello" = "World" }' + + $result = Import-PowerShellDataFile $path -ErrorAction Stop + $result.Hello | Should be "World" + } + +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/alias.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/alias.tests.ps1 index 2ed3956d62..4317e8d211 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/alias.tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/alias.tests.ps1 @@ -1,160 +1,160 @@ -Describe "Alias tests" -Tags "CI" { - - BeforeAll { - $testPath = Join-Path testdrive:\ ("testAlias\[.test") - New-Item -ItemType Directory -Path $testPath -Force | Out-Null - - class TestData - { - [string] $testName - [string] $testFile - [string] $expectedError - - TestData($name, $file, $error) - { - $this.testName = $name - $this.testFile = $file - $this.expectedError = $error - } - } - } - - Context "Export-Alias literal path" { - BeforeAll { - $csvFile = Join-Path $testPath "alias.csv" - $ps1File = Join-Path $testPath "alias.ps1" - - $testCases = @() - $testCases += [TestData]::new("CSV", $csvFile, [NullString]::Value) - $testCases += [TestData]::new("PS1", $ps1File, [NullString]::Value) - $testCases += [TestData]::new("Empty string", "", "ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.ExportAliasCommand") - $testCases += [TestData]::new("Null", [NullString]::Value, "ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ExportAliasCommand") - $testCases += [TestData]::new("Non filesystem provider", 'cert:\alias.ps1', "ReadWriteFileNotFileSystemProvider,Microsoft.PowerShell.Commands.ExportAliasCommand") - } - - $testCases | % { - - It "for $($_.testName)" { - - $test = $_ - try - { - Export-Alias -LiteralPath $test.testFile -ErrorAction SilentlyContinue - } - catch - { - $exportAliasError = $_ - } - - if($test.expectedError -eq $null) - { - Test-Path -LiteralPath $test.testFile | Should Be $true - } - else - { - $exportAliasError.FullyqualifiedErrorId | Should Be $test.expectedError - } - } - - AfterEach { - Remove-Item -LiteralPath $test.testFile -Force -ErrorAction SilentlyContinue - } - } - - It "when file exists with NoClobber" { - Export-Alias -LiteralPath $csvFile - - try - { - Export-Alias -LiteralPath $csvFile -NoClobber - } - catch - { - $exportAliasError = $_ - } - - $exportAliasError.FullyQualifiedErrorId | Should Be "NoClobber,Microsoft.PowerShell.Commands.ExportAliasCommand" - } - } - - Context "Export-All inside a literal path" { - BeforeEach { - Push-Location -LiteralPath $testPath - } - - It "with a CSV file" { - Export-Alias "alias.csv" - Test-Path -LiteralPath (Join-Path $testPath "alias.csv") | Should Be $true - } - - It "with NoClobber" { - $path = Export-Alias alias.csv - - try - { - Export-Alias alias.csv -NoClobber - } - catch - { - $exportAliasError = $_ - } - - $exportAliasError.FullyQualifiedErrorId | Should Be "NoClobber,Microsoft.PowerShell.Commands.ExportAliasCommand" - } - - AfterEach { - Pop-Location - } - } - - Context "Import-Alias literal path" { - - BeforeAll { - $csvFile = Join-Path $testPath "alias.csv" - $ps1File = Join-Path $testPath "alias.ps1" - - $testCases = @() - $testCases += [TestData]::new("Empty string", "", "ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.ImportAliasCommand") - $testCases += [TestData]::new("Null", [NullString]::Value, "ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ImportAliasCommand") - $testCases += [TestData]::new("Non filesystem provider", 'cert:\alias.ps1', "NotSupported,Microsoft.PowerShell.Commands.ImportAliasCommand") - } - - $testCases | % { - - It "for $($_.testName)" { - $test = $_ - - try - { - Import-Alias -LiteralPath $test.testFile -ErrorAction SilentlyContinue - } - catch - { - $exportAliasError = $_ - } - - $exportAliasError.FullyqualifiedErrorId | Should Be $test.expectedError - } - } - - It "can be done from a CSV file" { - - # alias file definition content - $aliasDefinition = @' - "myuh","update-help","","ReadOnly, AllScope" -'@ - - $aliasFile = Join-Path $testPath "alias.csv" - $aliasDefinition | Out-File -LiteralPath $aliasFile - - Import-Alias -LiteralPath $aliasFile - - # Verify that the alias was imported - $definedAlias = Get-Alias myuh - - $definedAlias | Should Not Be $null - $definedAlias.Name | Should Be "myuh" - $definedAlias.Definition | Should Be "update-help" - } - } -} +Describe "Alias tests" -Tags "CI" { + + BeforeAll { + $testPath = Join-Path testdrive:\ ("testAlias\[.test") + New-Item -ItemType Directory -Path $testPath -Force | Out-Null + + class TestData + { + [string] $testName + [string] $testFile + [string] $expectedError + + TestData($name, $file, $error) + { + $this.testName = $name + $this.testFile = $file + $this.expectedError = $error + } + } + } + + Context "Export-Alias literal path" { + BeforeAll { + $csvFile = Join-Path $testPath "alias.csv" + $ps1File = Join-Path $testPath "alias.ps1" + + $testCases = @() + $testCases += [TestData]::new("CSV", $csvFile, [NullString]::Value) + $testCases += [TestData]::new("PS1", $ps1File, [NullString]::Value) + $testCases += [TestData]::new("Empty string", "", "ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.ExportAliasCommand") + $testCases += [TestData]::new("Null", [NullString]::Value, "ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ExportAliasCommand") + $testCases += [TestData]::new("Non filesystem provider", 'cert:\alias.ps1', "ReadWriteFileNotFileSystemProvider,Microsoft.PowerShell.Commands.ExportAliasCommand") + } + + $testCases | % { + + It "for $($_.testName)" { + + $test = $_ + try + { + Export-Alias -LiteralPath $test.testFile -ErrorAction SilentlyContinue + } + catch + { + $exportAliasError = $_ + } + + if($test.expectedError -eq $null) + { + Test-Path -LiteralPath $test.testFile | Should Be $true + } + else + { + $exportAliasError.FullyqualifiedErrorId | Should Be $test.expectedError + } + } + + AfterEach { + Remove-Item -LiteralPath $test.testFile -Force -ErrorAction SilentlyContinue + } + } + + It "when file exists with NoClobber" { + Export-Alias -LiteralPath $csvFile + + try + { + Export-Alias -LiteralPath $csvFile -NoClobber + } + catch + { + $exportAliasError = $_ + } + + $exportAliasError.FullyQualifiedErrorId | Should Be "NoClobber,Microsoft.PowerShell.Commands.ExportAliasCommand" + } + } + + Context "Export-All inside a literal path" { + BeforeEach { + Push-Location -LiteralPath $testPath + } + + It "with a CSV file" { + Export-Alias "alias.csv" + Test-Path -LiteralPath (Join-Path $testPath "alias.csv") | Should Be $true + } + + It "with NoClobber" { + $path = Export-Alias alias.csv + + try + { + Export-Alias alias.csv -NoClobber + } + catch + { + $exportAliasError = $_ + } + + $exportAliasError.FullyQualifiedErrorId | Should Be "NoClobber,Microsoft.PowerShell.Commands.ExportAliasCommand" + } + + AfterEach { + Pop-Location + } + } + + Context "Import-Alias literal path" { + + BeforeAll { + $csvFile = Join-Path $testPath "alias.csv" + $ps1File = Join-Path $testPath "alias.ps1" + + $testCases = @() + $testCases += [TestData]::new("Empty string", "", "ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.ImportAliasCommand") + $testCases += [TestData]::new("Null", [NullString]::Value, "ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ImportAliasCommand") + $testCases += [TestData]::new("Non filesystem provider", 'cert:\alias.ps1', "NotSupported,Microsoft.PowerShell.Commands.ImportAliasCommand") + } + + $testCases | % { + + It "for $($_.testName)" { + $test = $_ + + try + { + Import-Alias -LiteralPath $test.testFile -ErrorAction SilentlyContinue + } + catch + { + $exportAliasError = $_ + } + + $exportAliasError.FullyqualifiedErrorId | Should Be $test.expectedError + } + } + + It "can be done from a CSV file" { + + # alias file definition content + $aliasDefinition = @' + "myuh","update-help","","ReadOnly, AllScope" +'@ + + $aliasFile = Join-Path $testPath "alias.csv" + $aliasDefinition | Out-File -LiteralPath $aliasFile + + Import-Alias -LiteralPath $aliasFile + + # Verify that the alias was imported + $definedAlias = Get-Alias myuh + + $definedAlias | Should Not Be $null + $definedAlias.Name | Should Be "myuh" + $definedAlias.Definition | Should Be "update-help" + } + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/clixml.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/clixml.tests.ps1 index 4ae5261457..15477eae9b 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/clixml.tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/clixml.tests.ps1 @@ -1,187 +1,187 @@ -Describe "CliXml test" -Tags "CI" { - - BeforeAll { - $testFilePath = Join-Path "testdrive:\" "testCliXml" - $subFilePath = Join-Path $testFilePath ".test" - - if(test-path $testFilePath) - { - Remove-Item $testFilePath -Force -Recurse - } - - # Create the test File and push the location into specified path - New-Item -Path $testFilePath -ItemType Directory | Out-Null - New-Item -Path $subFilePath -ItemType Directory | Out-Null - Push-Location $testFilePath - - class TestData - { - [string] $testName - [object] $inputObject - [string] $expectedError - [string] $testFile - - TestData($name, $file, $inputObj, $error) - { - $this.testName = $name - $this.inputObject = $inputObj - $this.expectedError = $error - $this.testFile = $file - } - } - } - - AfterAll { - Pop-Location - } - - Context "Export-CliXml" { - BeforeAll { - $gpsList = Get-Process powershell - $gps = $gpsList | Select-Object -First 1 - $filePath = Join-Path $subFilePath 'gps.xml' - - $testData = @() - $testData += [TestData]::new("with path as Null", [NullString]::Value, $gps, "ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ExportClixmlCommand") - $testData += [TestData]::new("with path as Empty string", "", $gps, "ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.ExportClixmlCommand") - $testData += [TestData]::new("with path as non filesystem provider", "cert:\", $gps, "ReadWriteFileNotFileSystemProvider,Microsoft.PowerShell.Commands.ExportClixmlCommand") - } - - AfterEach { - Remove-Item $filePath -Force -ErrorAction SilentlyContinue - } - - $testData | % { - - It "$($_.testName)" { - $test = $_ - - try - { - Export-Clixml -LiteralPath $test.testFile -InputObject $test.inputObject -Force - } - catch - { - $exportCliXmlError = $_ - } - - $exportCliXmlError.FullyQualifiedErrorId | Should Be $test.expectedError - } - } - - It "can be created with literal path" { - - $filePath = Join-Path $subFilePath 'gps.xml' - Export-Clixml -LiteralPath $filePath -InputObject ($gpsList | Select-Object -First 1) - - $filePath | Should Exist - - $fileContent = Get-Content $filePath - $isExisted = $false - - foreach($item in $fileContent) - { - foreach($gpsItem in $gpsList) - { - $checkId = $gpsItem.Id - if (($null -ne $(Select-String -InputObject $item -SimpleMatch $checkId)) -and ($null -ne $(Select-String -InputObject $item -SimpleMatch "Id"))) - { - $isExisted = $true - break; - } - } - } - - $isExisted | Should Be $true - } - - It "can be created with literal path using pipeline" { - - - $filePath = Join-Path $subFilePath 'gps.xml' - ($gpsList | Select-Object -First 1) | Export-Clixml -LiteralPath $filePath - - $filePath | Should Exist - - $fileContent = Get-Content $filePath - $isExisted = $false - - foreach($item in $fileContent) - { - foreach($gpsItem in $gpsList) - { - $checkId = $gpsItem.Id - if (($null -ne $(Select-String -InputObject $item -SimpleMatch $checkId)) -and ($null -ne $(Select-String -InputObject $item -SimpleMatch "Id"))) - { - $isExisted = $true - break; - } - } - } - - $isExisted | Should Be $true - } - } - - Context "Import-CliXML" { - BeforeAll { - $gpsList = Get-Process powershell - $gps = $gpsList | Select-Object -First 1 - $filePath = Join-Path $subFilePath 'gps.xml' - - $testData = @() - $testData += [TestData]::new("with path as Null", [NullString]::Value, $null, "ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ImportClixmlCommand") - $testData += [TestData]::new("with path as Empty string", "", $null, "ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.ImportClixmlCommand") - $testData += [TestData]::new("with path as non filesystem provider", "cert:\", $null, "ReadWriteFileNotFileSystemProvider,Microsoft.PowerShell.Commands.ImportClixmlCommand") - } - - $testData | % { - - It "$($_.testName)" { - $test = $_ - - try - { - Import-Clixml -LiteralPath $test.testFile - } - catch - { - $importCliXmlError = $_ - } - - $importCliXmlError.FullyQualifiedErrorId | Should Be $test.expectedError - } - } - - It "can import from a literal path" { - Export-Clixml -LiteralPath $filePath -InputObject $gps - $filePath | Should Exist - - $fileContent = Get-Content $filePath - $fileContent | Should Not Be $null - - $importedProcess = Import-Clixml $filePath - $gps.ProcessName | Should Be $importedProcess.ProcessName - $gps.Id | Should Be $importedProcess.Id - } - - It "can import from a literal path using pipeline" { - $gps | Export-Clixml -LiteralPath $filePath - $filePath | Should Exist - - $fileContent = Get-Content $filePath - $fileContent | Should Not Be $null - - $importedProcess = Import-Clixml $filePath - $gps.ProcessName | Should Be $importedProcess.ProcessName - $gps.Id | Should Be $importedProcess.Id - } - - It "test follow-up for WinBlue: 161470 - Export-CliXml errors in WhatIf scenarios" { - - $testPath = "testdrive:\Bug161470NonExistPath.txt" - Export-Clixml -Path $testPath -InputObject "string" -WhatIf - $testPath | Should Not Exist - } - } -} +Describe "CliXml test" -Tags "CI" { + + BeforeAll { + $testFilePath = Join-Path "testdrive:\" "testCliXml" + $subFilePath = Join-Path $testFilePath ".test" + + if(test-path $testFilePath) + { + Remove-Item $testFilePath -Force -Recurse + } + + # Create the test File and push the location into specified path + New-Item -Path $testFilePath -ItemType Directory | Out-Null + New-Item -Path $subFilePath -ItemType Directory | Out-Null + Push-Location $testFilePath + + class TestData + { + [string] $testName + [object] $inputObject + [string] $expectedError + [string] $testFile + + TestData($name, $file, $inputObj, $error) + { + $this.testName = $name + $this.inputObject = $inputObj + $this.expectedError = $error + $this.testFile = $file + } + } + } + + AfterAll { + Pop-Location + } + + Context "Export-CliXml" { + BeforeAll { + $gpsList = Get-Process powershell + $gps = $gpsList | Select-Object -First 1 + $filePath = Join-Path $subFilePath 'gps.xml' + + $testData = @() + $testData += [TestData]::new("with path as Null", [NullString]::Value, $gps, "ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ExportClixmlCommand") + $testData += [TestData]::new("with path as Empty string", "", $gps, "ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.ExportClixmlCommand") + $testData += [TestData]::new("with path as non filesystem provider", "cert:\", $gps, "ReadWriteFileNotFileSystemProvider,Microsoft.PowerShell.Commands.ExportClixmlCommand") + } + + AfterEach { + Remove-Item $filePath -Force -ErrorAction SilentlyContinue + } + + $testData | % { + + It "$($_.testName)" { + $test = $_ + + try + { + Export-Clixml -LiteralPath $test.testFile -InputObject $test.inputObject -Force + } + catch + { + $exportCliXmlError = $_ + } + + $exportCliXmlError.FullyQualifiedErrorId | Should Be $test.expectedError + } + } + + It "can be created with literal path" { + + $filePath = Join-Path $subFilePath 'gps.xml' + Export-Clixml -LiteralPath $filePath -InputObject ($gpsList | Select-Object -First 1) + + $filePath | Should Exist + + $fileContent = Get-Content $filePath + $isExisted = $false + + foreach($item in $fileContent) + { + foreach($gpsItem in $gpsList) + { + $checkId = $gpsItem.Id + if (($null -ne $(Select-String -InputObject $item -SimpleMatch $checkId)) -and ($null -ne $(Select-String -InputObject $item -SimpleMatch "Id"))) + { + $isExisted = $true + break; + } + } + } + + $isExisted | Should Be $true + } + + It "can be created with literal path using pipeline" { + + + $filePath = Join-Path $subFilePath 'gps.xml' + ($gpsList | Select-Object -First 1) | Export-Clixml -LiteralPath $filePath + + $filePath | Should Exist + + $fileContent = Get-Content $filePath + $isExisted = $false + + foreach($item in $fileContent) + { + foreach($gpsItem in $gpsList) + { + $checkId = $gpsItem.Id + if (($null -ne $(Select-String -InputObject $item -SimpleMatch $checkId)) -and ($null -ne $(Select-String -InputObject $item -SimpleMatch "Id"))) + { + $isExisted = $true + break; + } + } + } + + $isExisted | Should Be $true + } + } + + Context "Import-CliXML" { + BeforeAll { + $gpsList = Get-Process powershell + $gps = $gpsList | Select-Object -First 1 + $filePath = Join-Path $subFilePath 'gps.xml' + + $testData = @() + $testData += [TestData]::new("with path as Null", [NullString]::Value, $null, "ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ImportClixmlCommand") + $testData += [TestData]::new("with path as Empty string", "", $null, "ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.ImportClixmlCommand") + $testData += [TestData]::new("with path as non filesystem provider", "cert:\", $null, "ReadWriteFileNotFileSystemProvider,Microsoft.PowerShell.Commands.ImportClixmlCommand") + } + + $testData | % { + + It "$($_.testName)" { + $test = $_ + + try + { + Import-Clixml -LiteralPath $test.testFile + } + catch + { + $importCliXmlError = $_ + } + + $importCliXmlError.FullyQualifiedErrorId | Should Be $test.expectedError + } + } + + It "can import from a literal path" { + Export-Clixml -LiteralPath $filePath -InputObject $gps + $filePath | Should Exist + + $fileContent = Get-Content $filePath + $fileContent | Should Not Be $null + + $importedProcess = Import-Clixml $filePath + $gps.ProcessName | Should Be $importedProcess.ProcessName + $gps.Id | Should Be $importedProcess.Id + } + + It "can import from a literal path using pipeline" { + $gps | Export-Clixml -LiteralPath $filePath + $filePath | Should Exist + + $fileContent = Get-Content $filePath + $fileContent | Should Not Be $null + + $importedProcess = Import-Clixml $filePath + $gps.ProcessName | Should Be $importedProcess.ProcessName + $gps.Id | Should Be $importedProcess.Id + } + + It "test follow-up for WinBlue: 161470 - Export-CliXml errors in WhatIf scenarios" { + + $testPath = "testdrive:\Bug161470NonExistPath.txt" + Export-Clixml -Path $testPath -InputObject "string" -WhatIf + $testPath | Should Not Exist + } + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/command.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/command.tests.ps1 index 94d554989b..6aeb05ad2e 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/command.tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/command.tests.ps1 @@ -1,80 +1,80 @@ -Describe "Trace-Command" -tags "Feature" { - - Context "Listner options" { - BeforeAll { - $logFile = setup -f traceCommandLog.txt -pass - $actualLogFile = setup -f actualTraceCommandLog.txt -pass - } - - AfterEach { - if ( test-path $logfile ) { Remove-Item $logFile } - if ( test-path $actualLogFile ) { Remove-Item $actualLogFile } - } - - It "LogicalOperationStack works" -pending:($IsCore) { - $keyword = "Trace_Command_ListenerOption_LogicalOperationStack_Foo" - $stack = [System.Diagnostics.Trace]::CorrelationManager.LogicalOperationStack - $stack.Push($keyword) - - Trace-Command -Name * -Expression {write-output Foo} -ListenerOption LogicalOperationStack -FilePath $logfile - - $log = Get-Content $logfile | Where-Object {$_ -like "*LogicalOperationStack=$keyword*"} - $log.Count | Should BeGreaterThan 0 - } - - It "Callstack works" -pending:($IsCore) { - Trace-Command -Name * -Expression {write-output Foo} -ListenerOption Callstack -FilePath $logfile - $log = Get-Content $logfile | Where-Object {$_ -like "*Callstack= * System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)*"} - $log.Count | Should BeGreaterThan 0 - } - - It "Datetime works" { - $expectedDate = Trace-Command -Name * -Expression {Get-Date} -ListenerOption DateTime -FilePath $logfile - $log = Get-Content $logfile | Where-Object {$_ -like "*DateTime=*"} - $results = $log | ForEach-Object {[DateTime]::Parse($_.Split("=")[1])} - - ## allow a gap of 6 seconds. All traces should be finished within 6 seconds. - $allowedGap = [timespan](60 * 1000 * 1000) - $results | ForEach-Object { - $actualGap = $_ - $expectedDate; - if ($expectedDate -gt $_) - { - $actualGap = $expectedDate - $_; - } - - $allowedGap | Should BeGreaterThan $actualGap - } - } - - It "None options has no effect" { - Trace-Command -Name * -Expression {write-output Foo} -ListenerOption None -FilePath $actualLogfile - Trace-Command -name * -Expression {write-output Foo} -FilePath $logfile - - Compare-Object (Get-Content $actualLogfile) (Get-Content $logfile) | Should BeNullOrEmpty - } - - It "ThreadID works" { - Trace-Command -Name * -Expression {write-output Foo} -ListenerOption ThreadId -FilePath $logfile - $log = Get-Content $logfile | Where-Object {$_ -like "*ThreadID=*"} - $results = $log | ForEach-Object {$_.Split("=")[1]} - - $results | % { $_ | Should Be ([threading.thread]::CurrentThread.ManagedThreadId) } - } - - It "Timestamp creates logs in ascending order" { - Trace-Command -Name * -Expression {write-output Foo} -ListenerOption Timestamp -FilePath $logfile - $log = Get-Content $logfile | Where-Object {$_ -like "*Timestamp=*"} - $results = $log | ForEach-Object {$_.Split("=")[1]} - $sortedResults = $results | Sort-Object - $sortedResults | Should Be $results - } - - It "ProcessId logs current process Id" { - Trace-Command -Name * -Expression {write-output Foo} -ListenerOption ProcessId -FilePath $logfile - $log = Get-Content $logfile | Where-Object {$_ -like "*ProcessID=*"} - $results = $log | ForEach-Object {$_.Split("=")[1]} - - $results | ForEach-Object { $_ | Should Be $pid } - } - } -} +Describe "Trace-Command" -tags "Feature" { + + Context "Listner options" { + BeforeAll { + $logFile = setup -f traceCommandLog.txt -pass + $actualLogFile = setup -f actualTraceCommandLog.txt -pass + } + + AfterEach { + if ( test-path $logfile ) { Remove-Item $logFile } + if ( test-path $actualLogFile ) { Remove-Item $actualLogFile } + } + + It "LogicalOperationStack works" -pending:($IsCore) { + $keyword = "Trace_Command_ListenerOption_LogicalOperationStack_Foo" + $stack = [System.Diagnostics.Trace]::CorrelationManager.LogicalOperationStack + $stack.Push($keyword) + + Trace-Command -Name * -Expression {write-output Foo} -ListenerOption LogicalOperationStack -FilePath $logfile + + $log = Get-Content $logfile | Where-Object {$_ -like "*LogicalOperationStack=$keyword*"} + $log.Count | Should BeGreaterThan 0 + } + + It "Callstack works" -pending:($IsCore) { + Trace-Command -Name * -Expression {write-output Foo} -ListenerOption Callstack -FilePath $logfile + $log = Get-Content $logfile | Where-Object {$_ -like "*Callstack= * System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)*"} + $log.Count | Should BeGreaterThan 0 + } + + It "Datetime works" { + $expectedDate = Trace-Command -Name * -Expression {Get-Date} -ListenerOption DateTime -FilePath $logfile + $log = Get-Content $logfile | Where-Object {$_ -like "*DateTime=*"} + $results = $log | ForEach-Object {[DateTime]::Parse($_.Split("=")[1])} + + ## allow a gap of 6 seconds. All traces should be finished within 6 seconds. + $allowedGap = [timespan](60 * 1000 * 1000) + $results | ForEach-Object { + $actualGap = $_ - $expectedDate; + if ($expectedDate -gt $_) + { + $actualGap = $expectedDate - $_; + } + + $allowedGap | Should BeGreaterThan $actualGap + } + } + + It "None options has no effect" { + Trace-Command -Name * -Expression {write-output Foo} -ListenerOption None -FilePath $actualLogfile + Trace-Command -name * -Expression {write-output Foo} -FilePath $logfile + + Compare-Object (Get-Content $actualLogfile) (Get-Content $logfile) | Should BeNullOrEmpty + } + + It "ThreadID works" { + Trace-Command -Name * -Expression {write-output Foo} -ListenerOption ThreadId -FilePath $logfile + $log = Get-Content $logfile | Where-Object {$_ -like "*ThreadID=*"} + $results = $log | ForEach-Object {$_.Split("=")[1]} + + $results | % { $_ | Should Be ([threading.thread]::CurrentThread.ManagedThreadId) } + } + + It "Timestamp creates logs in ascending order" { + Trace-Command -Name * -Expression {write-output Foo} -ListenerOption Timestamp -FilePath $logfile + $log = Get-Content $logfile | Where-Object {$_ -like "*Timestamp=*"} + $results = $log | ForEach-Object {$_.Split("=")[1]} + $sortedResults = $results | Sort-Object + $sortedResults | Should Be $results + } + + It "ProcessId logs current process Id" { + Trace-Command -Name * -Expression {write-output Foo} -ListenerOption ProcessId -FilePath $logfile + $log = Get-Content $logfile | Where-Object {$_ -like "*ProcessID=*"} + $results = $log | ForEach-Object {$_.Split("=")[1]} + + $results | ForEach-Object { $_ | Should Be $pid } + } + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/formatdata.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/formatdata.tests.ps1 index d1f08eeefc..14f8fc76da 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/formatdata.tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/formatdata.tests.ps1 @@ -1,64 +1,64 @@ -Describe "FormatData" -tags "Feature" { - - Context "Export" { - It "can export all types" { - try - { - $expectAllFormat = Get-FormatData -typename * - $expectAllFormat | Export-FormatData -path $TESTDRIVE\allformat.ps1xml -IncludeScriptBlock - - $sessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault() - $sessionState.Formats.Clear() - $sessionState.Types.Clear() - - $runspace = [System.Management.Automation.Runspaces.RunspaceFactory]::CreateRunspace($sessionState) - $runspace.Open() - - $runspace.CreatePipeline("Update-FormatData -AppendPath $TESTDRIVE\allformat.ps1xml").Invoke() - $actualAllFormat = $runspace.CreatePipeline("Get-FormatData -TypeName *").Invoke() - - $expectAllFormat.Count | Should Be $actualAllFormat.Count - Compare-Object $expectAllFormat $actualAllFormat | Should Be $null - $runspace.Close() - } - finally - { - Remove-Item -Path $TESTDRIVE\allformat.ps1xml -Force -ErrorAction SilentlyContinue - } - } - - It "works with literal path" { - $filename = 'TestDrive:\[formats.ps1xml' - Get-FormatData -TypeName * | Export-FormatData -LiteralPath $filename - (Test-Path -LiteralPath $filename) | Should Be $true - } - - It "should overwrite the destination file" { - $filename = 'TestDrive:\ExportFormatDataWithForce.ps1xml' - $unexpected = "SHOULD BE OVERWRITTEN" - $unexpected | Out-File -FilePath $filename -Force - $file = Get-Item $filename - $file.IsReadOnly = $true - Get-FormatData -TypeName * | Export-FormatData -Path $filename -Force - - $actual = @(Get-Content $filename)[0] - $actual | Should Not Be $unexpected - } - - It "should not overwrite the destination file with NoClobber" { - $filename = "TestDrive:\ExportFormatDataWithNoClobber.ps1xml" - Get-FormatData -TypeName * | Export-FormatData -LiteralPath $filename - - try - { - Get-FormatData -TypeName * | Export-FormatData -LiteralPath $filename -NoClobber - } - catch - { - $exportFormatError = $_ - } - - $exportFormatError.FullyQualifiedErrorId | Should Be 'NoClobber,Microsoft.PowerShell.Commands.ExportFormatDataCommand' - } - } -} +Describe "FormatData" -tags "Feature" { + + Context "Export" { + It "can export all types" { + try + { + $expectAllFormat = Get-FormatData -typename * + $expectAllFormat | Export-FormatData -path $TESTDRIVE\allformat.ps1xml -IncludeScriptBlock + + $sessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault() + $sessionState.Formats.Clear() + $sessionState.Types.Clear() + + $runspace = [System.Management.Automation.Runspaces.RunspaceFactory]::CreateRunspace($sessionState) + $runspace.Open() + + $runspace.CreatePipeline("Update-FormatData -AppendPath $TESTDRIVE\allformat.ps1xml").Invoke() + $actualAllFormat = $runspace.CreatePipeline("Get-FormatData -TypeName *").Invoke() + + $expectAllFormat.Count | Should Be $actualAllFormat.Count + Compare-Object $expectAllFormat $actualAllFormat | Should Be $null + $runspace.Close() + } + finally + { + Remove-Item -Path $TESTDRIVE\allformat.ps1xml -Force -ErrorAction SilentlyContinue + } + } + + It "works with literal path" { + $filename = 'TestDrive:\[formats.ps1xml' + Get-FormatData -TypeName * | Export-FormatData -LiteralPath $filename + (Test-Path -LiteralPath $filename) | Should Be $true + } + + It "should overwrite the destination file" { + $filename = 'TestDrive:\ExportFormatDataWithForce.ps1xml' + $unexpected = "SHOULD BE OVERWRITTEN" + $unexpected | Out-File -FilePath $filename -Force + $file = Get-Item $filename + $file.IsReadOnly = $true + Get-FormatData -TypeName * | Export-FormatData -Path $filename -Force + + $actual = @(Get-Content $filename)[0] + $actual | Should Not Be $unexpected + } + + It "should not overwrite the destination file with NoClobber" { + $filename = "TestDrive:\ExportFormatDataWithNoClobber.ps1xml" + Get-FormatData -TypeName * | Export-FormatData -LiteralPath $filename + + try + { + Get-FormatData -TypeName * | Export-FormatData -LiteralPath $filename -NoClobber + } + catch + { + $exportFormatError = $_ + } + + $exportFormatError.FullyQualifiedErrorId | Should Be 'NoClobber,Microsoft.PowerShell.Commands.ExportFormatDataCommand' + } + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/object.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/object.tests.ps1 index 41d4bf2ea2..6a8d1e25c1 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/object.tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/object.tests.ps1 @@ -1,100 +1,100 @@ -Describe "Object cmdlets" -Tags "CI" { - Context "Group-Object" { - It "AsHashtable returns a hashtable" { - $result = Get-Process | Group-Object -Property ProcessName -AsHashTable - $result["powershell"].Count | Should BeGreaterThan 0 - } - - It "AsString returns a string" { - $processes = Get-Process | Group-Object -Property ProcessName -AsHashTable -AsString - $result = $processes.Keys | ForEach-Object {$_.GetType()} - $result[0].Name | Should Be "String" - } - } - - Context "Tee-Object" { - It "with literal path" { - $path = "TestDrive:\[TeeObjectLiteralPathShouldWorkForSpecialFilename].txt" - Write-Output "Test" | Tee-Object -LiteralPath $path | Tee-Object -Variable TeeObjectLiteralPathShouldWorkForSpecialFilename - $TeeObjectLiteralPathShouldWorkForSpecialFilename | Should Be (Get-Content -LiteralPath $path) - } - } -} - -Describe "Object cmdlets" -Tags "CI" { - Context "Measure-Object" { - BeforeAll { - ## Powershell language prefers , as an array seperator without "". - ## If a number has comma in them it considers it to be the 1000 seperator like "1,000". - ## In de-DE language the comma is used as decimal point, but powershell still uses it as a 1000 seperator. - ## In case the number has a comma, it is ignored. So, "99,1" becomes 991. - ## To work around that behavior, we use ToString() on the expected answer and . for decimal in the input. - - $firstValue = "9995788.71" - $expectedFirstValue = $null - $null = [System.Management.Automation.LanguagePrimitives]::TryConvertTo($firstValue, [double], [cultureinfo]::InvariantCulture, [ref] $expectedFirstValue) - $firstObject = new-object psobject - $firstObject | Add-Member -NotePropertyName Header -NotePropertyValue $firstValue - - $secondValue = "15847577.7" - $expectedSecondValue = $null - $null = [System.Management.Automation.LanguagePrimitives]::TryConvertTo($secondValue, [double], [cultureinfo]::InvariantCulture, [ref] $expectedSecondValue) - $secondObject = new-object psobject - $secondObject | Add-Member -NotePropertyName Header -NotePropertyValue $secondValue - - $testCases = @( - @{ data = @("abc","ABC","Def"); min = "abc"; max = "Def"}, - @{ data = @([datetime]::Today, [datetime]::Today.AddDays(-1)); min = ([datetime]::Today.AddDays(-1)).ToString() ; max = [datetime]::Today.ToString() } - @{ data = @(1,2,3,"ABC"); min = 1; max = "ABC"}, - @{ data = @(4,2,3,"ABC",1); min = 1; max = "ABC"}, - @{ data = @(4,2,3,"ABC",1,"DEF"); min = 1; max = "DEF"}, - @{ data = @("111 Test","19"); min = "111 Test"; max = "19"}, - @{ data = @("19", "111 Test"); min = "111 Test"; max = "19"}, - @{ data = @("111 Test",19); min = "111 Test"; max = 19}, - @{ data = @(19, "111 Test"); min = "111 Test"; max = 19}, - @{ data = @(100,2,3, "A", 1); min = 1; max = "A"}, - @{ data = @(4,2,3, "ABC", 1, "DEF"); min = 1; max = "DEF"}, - @{ data = @("abc",[Datetime]::Today,"def"); min = [Datetime]::Today.ToString(); max = "def"} - ) - } - - It "can compare string representation for minimum" { - $minResult = $firstObject, $secondObject | Measure-Object Header -Minimum - $minResult.Minimum.ToString() | Should Be $expectedFirstValue.ToString() - } - - It "can compare string representation for maximum" { - $maxResult = $firstObject, $secondObject | Measure-Object Header -Maximum - $maxResult.Maximum.ToString() | Should Be $expectedSecondValue.ToString() - } - - It 'correctly find minimum of ()' -TestCases $testCases { - param($data, $min, $max) - - $output = $data | Measure-Object -Minimum - $output.Minimum.ToString() | Should Be $min - } - - It 'correctly find maximum of ()' -TestCases $testCases { - param($data, $min, $max) - - $output = $data | Measure-Object -Maximum - $output.Maximum.ToString() | Should Be $max - } - - It 'returns a GenericMeasureInfoObject' { - $gmi = 1,2,3 | measure-object -max -min - $gmi.GetType().FullName | Should Be 'Microsoft.PowerShell.Commands.GenericMeasureInfo' - } - - It 'should return correct error for non-numeric input' { - $gmi = "abc",[Datetime]::Now | measure -sum -max -ev err -ea silentlycontinue - $err | % { $_.FullyQualifiedErrorId | Should Be 'NonNumericInputObject,Microsoft.PowerShell.Commands.MeasureObjectCommand' } - } - - It 'should have the correct count' { - $gmi = "abc",[Datetime]::Now | measure -sum -max -ev err -ea silentlycontinue - $gmi.Count | Should Be 2 - } - } -} +Describe "Object cmdlets" -Tags "CI" { + Context "Group-Object" { + It "AsHashtable returns a hashtable" { + $result = Get-Process | Group-Object -Property ProcessName -AsHashTable + $result["powershell"].Count | Should BeGreaterThan 0 + } + + It "AsString returns a string" { + $processes = Get-Process | Group-Object -Property ProcessName -AsHashTable -AsString + $result = $processes.Keys | ForEach-Object {$_.GetType()} + $result[0].Name | Should Be "String" + } + } + + Context "Tee-Object" { + It "with literal path" { + $path = "TestDrive:\[TeeObjectLiteralPathShouldWorkForSpecialFilename].txt" + Write-Output "Test" | Tee-Object -LiteralPath $path | Tee-Object -Variable TeeObjectLiteralPathShouldWorkForSpecialFilename + $TeeObjectLiteralPathShouldWorkForSpecialFilename | Should Be (Get-Content -LiteralPath $path) + } + } +} + +Describe "Object cmdlets" -Tags "CI" { + Context "Measure-Object" { + BeforeAll { + ## Powershell language prefers , as an array seperator without "". + ## If a number has comma in them it considers it to be the 1000 seperator like "1,000". + ## In de-DE language the comma is used as decimal point, but powershell still uses it as a 1000 seperator. + ## In case the number has a comma, it is ignored. So, "99,1" becomes 991. + ## To work around that behavior, we use ToString() on the expected answer and . for decimal in the input. + + $firstValue = "9995788.71" + $expectedFirstValue = $null + $null = [System.Management.Automation.LanguagePrimitives]::TryConvertTo($firstValue, [double], [cultureinfo]::InvariantCulture, [ref] $expectedFirstValue) + $firstObject = new-object psobject + $firstObject | Add-Member -NotePropertyName Header -NotePropertyValue $firstValue + + $secondValue = "15847577.7" + $expectedSecondValue = $null + $null = [System.Management.Automation.LanguagePrimitives]::TryConvertTo($secondValue, [double], [cultureinfo]::InvariantCulture, [ref] $expectedSecondValue) + $secondObject = new-object psobject + $secondObject | Add-Member -NotePropertyName Header -NotePropertyValue $secondValue + + $testCases = @( + @{ data = @("abc","ABC","Def"); min = "abc"; max = "Def"}, + @{ data = @([datetime]::Today, [datetime]::Today.AddDays(-1)); min = ([datetime]::Today.AddDays(-1)).ToString() ; max = [datetime]::Today.ToString() } + @{ data = @(1,2,3,"ABC"); min = 1; max = "ABC"}, + @{ data = @(4,2,3,"ABC",1); min = 1; max = "ABC"}, + @{ data = @(4,2,3,"ABC",1,"DEF"); min = 1; max = "DEF"}, + @{ data = @("111 Test","19"); min = "111 Test"; max = "19"}, + @{ data = @("19", "111 Test"); min = "111 Test"; max = "19"}, + @{ data = @("111 Test",19); min = "111 Test"; max = 19}, + @{ data = @(19, "111 Test"); min = "111 Test"; max = 19}, + @{ data = @(100,2,3, "A", 1); min = 1; max = "A"}, + @{ data = @(4,2,3, "ABC", 1, "DEF"); min = 1; max = "DEF"}, + @{ data = @("abc",[Datetime]::Today,"def"); min = [Datetime]::Today.ToString(); max = "def"} + ) + } + + It "can compare string representation for minimum" { + $minResult = $firstObject, $secondObject | Measure-Object Header -Minimum + $minResult.Minimum.ToString() | Should Be $expectedFirstValue.ToString() + } + + It "can compare string representation for maximum" { + $maxResult = $firstObject, $secondObject | Measure-Object Header -Maximum + $maxResult.Maximum.ToString() | Should Be $expectedSecondValue.ToString() + } + + It 'correctly find minimum of ()' -TestCases $testCases { + param($data, $min, $max) + + $output = $data | Measure-Object -Minimum + $output.Minimum.ToString() | Should Be $min + } + + It 'correctly find maximum of ()' -TestCases $testCases { + param($data, $min, $max) + + $output = $data | Measure-Object -Maximum + $output.Maximum.ToString() | Should Be $max + } + + It 'returns a GenericMeasureInfoObject' { + $gmi = 1,2,3 | measure-object -max -min + $gmi.GetType().FullName | Should Be 'Microsoft.PowerShell.Commands.GenericMeasureInfo' + } + + It 'should return correct error for non-numeric input' { + $gmi = "abc",[Datetime]::Now | measure -sum -max -ev err -ea silentlycontinue + $err | % { $_.FullyQualifiedErrorId | Should Be 'NonNumericInputObject,Microsoft.PowerShell.Commands.MeasureObjectCommand' } + } + + It 'should have the correct count' { + $gmi = "abc",[Datetime]::Now | measure -sum -max -ev err -ea silentlycontinue + $gmi.Count | Should Be 2 + } + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/string.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/string.tests.ps1 index bdcfa965d5..5f7c0e776c 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/string.tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/string.tests.ps1 @@ -1,63 +1,63 @@ -Describe "String cmdlets" -Tags "CI" { - Context "Select-String" { - BeforeAll { - $sep = [io.path]::DirectorySeparatorChar - $fileName = New-Item 'TestDrive:\selectStr[ingLi]teralPath.txt' - "abc" | Out-File -LiteralPath $fileName.fullname - "bcd" | Out-File -LiteralPath $fileName.fullname -Append - "cde" | Out-File -LiteralPath $fileName.fullname -Append - - $fileNameWithDots = $fileName.FullName.Replace("\", "\.\") - - $tempFile = New-TemporaryFile - "abc" | Out-File -LiteralPath $tempFile.fullname - "bcd" | Out-File -LiteralPath $tempFile.fullname -Append - "cde" | Out-File -LiteralPath $tempFile.fullname -Append - $driveLetter = $tempFile.PSDrive.Name - $fileNameAsNetworkPath = "\\localhost\$driveLetter`$" + $tempFile.FullName.SubString(2) - - Push-Location "$fileName\.." - } - - AfterAll { - Remove-Item $tempFile -Force -ErrorAction SilentlyContinue - Pop-Location - } - - It "LiteralPath with relative path" { - (select-string -LiteralPath (Get-Item -LiteralPath $fileName).Name "b").count | Should Be 2 - } - - It "LiteralPath with absolute path" { - (select-string -LiteralPath $fileName "b").count | Should Be 2 - } - - It "LiteralPath with dots in path" { - (select-string -LiteralPath $fileNameWithDots "b").count | Should Be 2 - } - - It "Network path" -skip:($IsCore) { - (select-string -LiteralPath $fileNameAsNetworkPath "b").count | Should Be 2 - } - - It "throws error for non filesystem providers" { - $aaa = "aaaaaaaaaa" - select-string -literalPath variable:\aaa "a" -ErrorAction SilentlyContinue -ErrorVariable selectStringError - $selectStringError.FullyQualifiedErrorId | Should Be 'ProcessingFile,Microsoft.PowerShell.Commands.SelectStringCommand' - } - - It "throws parameter binding exception for invalid context" { - { select-string It $PSScriptRoot -Context -1,-1 } | Should Throw Context - } - - It "match object supports RelativePath method" { - $file = "Modules${sep}Microsoft.PowerShell.Utility${sep}Microsoft.PowerShell.Utility.psd1" - - $match = Select-String CmdletsToExport $pshome/$file - - $match.RelativePath($pshome) | Should Be $file - $match.RelativePath($pshome.ToLower()) | Should Be $file - $match.RelativePath($pshome.ToUpper()) | Should Be $file - } - } -} +Describe "String cmdlets" -Tags "CI" { + Context "Select-String" { + BeforeAll { + $sep = [io.path]::DirectorySeparatorChar + $fileName = New-Item 'TestDrive:\selectStr[ingLi]teralPath.txt' + "abc" | Out-File -LiteralPath $fileName.fullname + "bcd" | Out-File -LiteralPath $fileName.fullname -Append + "cde" | Out-File -LiteralPath $fileName.fullname -Append + + $fileNameWithDots = $fileName.FullName.Replace("\", "\.\") + + $tempFile = New-TemporaryFile + "abc" | Out-File -LiteralPath $tempFile.fullname + "bcd" | Out-File -LiteralPath $tempFile.fullname -Append + "cde" | Out-File -LiteralPath $tempFile.fullname -Append + $driveLetter = $tempFile.PSDrive.Name + $fileNameAsNetworkPath = "\\localhost\$driveLetter`$" + $tempFile.FullName.SubString(2) + + Push-Location "$fileName\.." + } + + AfterAll { + Remove-Item $tempFile -Force -ErrorAction SilentlyContinue + Pop-Location + } + + It "LiteralPath with relative path" { + (select-string -LiteralPath (Get-Item -LiteralPath $fileName).Name "b").count | Should Be 2 + } + + It "LiteralPath with absolute path" { + (select-string -LiteralPath $fileName "b").count | Should Be 2 + } + + It "LiteralPath with dots in path" { + (select-string -LiteralPath $fileNameWithDots "b").count | Should Be 2 + } + + It "Network path" -skip:($IsCore) { + (select-string -LiteralPath $fileNameAsNetworkPath "b").count | Should Be 2 + } + + It "throws error for non filesystem providers" { + $aaa = "aaaaaaaaaa" + select-string -literalPath variable:\aaa "a" -ErrorAction SilentlyContinue -ErrorVariable selectStringError + $selectStringError.FullyQualifiedErrorId | Should Be 'ProcessingFile,Microsoft.PowerShell.Commands.SelectStringCommand' + } + + It "throws parameter binding exception for invalid context" { + { select-string It $PSScriptRoot -Context -1,-1 } | Should Throw Context + } + + It "match object supports RelativePath method" { + $file = "Modules${sep}Microsoft.PowerShell.Utility${sep}Microsoft.PowerShell.Utility.psd1" + + $match = Select-String CmdletsToExport $pshome/$file + + $match.RelativePath($pshome) | Should Be $file + $match.RelativePath($pshome.ToLower()) | Should Be $file + $match.RelativePath($pshome.ToUpper()) | Should Be $file + } + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/typedata.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/typedata.tests.ps1 index 5f88d447af4675db30638b6ea701ecea02873503..cf4c4233714c48880bfe43d6db0e75e32889ac8e 100644 GIT binary patch literal 5169 zcmdT|+fw635PkPobO~1h0Sm|@@sc&Slq&@xYqELR?86|nu@*_A%#1K%moLjhJ}JMD z?vY36VzM~JZYr*F*|J)FJKd*y{MR3U9-|IabcNtuqBh6E2ndoeMx#9#T#9QA-qF~D zk3FE*kxUKV8Ss8UGq@}=WO;X!1;%u5QfPyTKT=8*^?Q7Oqy8Y&B{zN6cPrPtp#L^fKke1f|5RSZ7#D#aWjdkP{5Fh(Ve zRFtYRKc#E!Fl{DQF~@3}nacE$!VpsviTIy2orzRjV?v_-C^s?@CX%UtF?oEx3Z)g* zhyuzCBzbJ2EJiRCWhb(}{S{s{QrSRh+g&a74iL<{ql677UA~DD%@Uta<^vJTEd?@0xy^$8pU7N3$@q2A4AgMZFGk z3TB3ykftjQq2$X*!Ca~vh*A)#q#qQhJk^;9NKS&dl~D)@YEA71dB%@GkSj$6R|#6n z6<7R{g~H%cx;R7v3P*9=>YqMyQfBruO%T4jkaJX%8OHJZ{e7xq(zfx4T`hg3x)Tx1 z+WIn0z$b}FL;4bY7&?jQk`i3L@B8{QZ+N9sX?{GY0_~V=}hXndscfroHjNU zOpaMbp~%PpWI_=e(zkXI*ruSw^vU2T3@0{M8?U`yE7Qc^j#A$;YWC7;KZ^n-wVWFN zF}?m#l<<3;Y9rDB7qY!&RmU28-s??&oZiZtPQ*+TpKDvIg7f2EHZb?p!nl7*rQ8_{ zt9b9UmmRmjv8v8Dn8@2NSDkEpf`%Gpa0+3bB*mU@Db&yO-dz&Iz;|&=tePBNh zh8*%iQ547g%y7qE4$m;TLPatq=8ij`kS5qlxx-inHwWuZ+xl>)b!)iOR=87{+F`d2 zhW0}rcvZP}Bl~uR$nNj&SBR`F-Ex23-G7rM zQj6`jSLK>>Nsk=U6X(*L@B@037IPX3=)qRGqr4$fmB}L?b6qr<$!qmkjhAf4vpw%A zB54yd(*sjN@pCTXXc}Q?`Fb2S=B-`P^l_1jBnnFNCwIKw&@!~WoIKokD5bgRdAVIo z4G*fiuT{s|+DG6yP!3X<$~cyDo{L1~SKM9nfqhG4jGqbZ6X@j^miAZY-x#Up8ETAE`Ijlac%Tu3y`uUT-M4d32_=1 l>$d+R7JS{9t;;%aS@dgb5A}5(yw4U_OZj6*Lx)AuZ_goAi)8ur4|Fx5NL^+D)_ zzRpi|_lnMJ=&q;XP`?ZwZa4}J(k1MM{nf9m}xyp&YO z(nUwVZpZUgv!uH4-S}}e&UGv;j5Oa^lA+0wP(Uwz9f$FK7`~p$SSCJ(PaNxbq%(MJPv3?*`#{!Fwtg8l&8Y3nuo`KFOe^6B ztTl@0W%_P@-3Gn2ZIZa&vo^Jw$Gjqtr9;IGo>^C;bhbT^h3 z@kjjgRQJ2pdQ2$OqFY5O-;;1X{Ic|z@*;Z9dRP-8rqS*2rM}tkjffS$a+Ee@8$>fK z$nU%wuF5*=B&+wza{1XqnFcn6A34S%;7_`1stCIn)!O5_qTM^Pi?JH%$C9{PE1`LU zOXA07|CqPM)SigN^?Iw0W!1CR$vKSP*)NrIUcN=SR<+v$;Xu|Sc9D5AS;`B2f)8i7 zMsDXCxvQh=ezm7jSvZOI_)6c%W<>g-&e(XagTqi`N4i1=U^H_)4R3Vp#SBY)o9M+1 zhq^|_^i|*`$C`y5V!?|urdGVjMt;;>9j%5G=iww|ee<=hqHbTWCT!OvfpIJ%=MAlk z#)x@O6lIR2DPj!Vf;`xlr`*uX;dY#a1@vI#%##~45k7-~Eog-^O(*m2v)=(}Xh zisXf3F+0)ZRV&OrGhQ@br#o@{i^m+h;%f66*bH}P_Lk#ORf#MQgW~R+GRR`IeJBJ5 zLgI~%xfL~6fN322x1+6V;gMvR&T`R)@FDvhOS*wr;D~ z&RPjK&v@k|+)94&-7&wVnR)Gn=4 z=rPea5B*A8iHe1F_7s^|<-U$n@lIc3B5pC%y(f`p!%bQBs@{2z@L}X3)G~t##_dt1 zj%%%iR2PfcuAF7%jKC$NmOU?rF}6!pjf9Kr+u4S*iqr6eatb}Eo>*H?V>$^}-`B6| zDl^ypL|Q+Uc3BS|n92_VFgrM%^`)*UuD554U_n>QYmszr$KH7a*)_i#e9O3ab!=G; ztE$uKA6i|P*1TD)`Z!O;<`t>&`e$ePkjf4wPd&>$aCvr)UcJJ#%Gc{+>XFyNfcwxB zT`f4Y`HTAsGg3V<6ZL}C(eP*_ER)hJ4yy)Ij|68buxqXS&MeAiNi#NGn&xU^N4V2N zLkAC}8TL&V>Okl4{5?t2i>&Zx-O+|cEyF9U=Cw{(wY^_2)pNBqIRci6Qv|Hz$2Z<2#>1O_!ea> z^QvaF)A*EP{yy-n^Tl-C@|^Qu^*_4DbO4B}bPTQ6==|hFSBcu3_X@SsDl)pIT~2TF z-7Pn^d3GswcYXCduC33iT2o`0<8&eKA? zBIi5SC(Yvd6R`!Jf92UIk8ACo^<50rgBiomBY3fPC1<4_5Fe4vs(^0E)4cf+`P}nN zHm}`_9SYWbES>Ztcgxh}xvr@3{u%pn{Wr}TplVNjum(pxw;Io27x(0J)r;n;kIQ>g z&9ub>&&1Dpc8w=nr9qe7tBLeUDD?xJbKH_s*7Rqyg?X6udXtG(G%j=^wZ}PO6Tq dJD>yeRv46bV6XcDtJFn(sA{{XUbAG`nn diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/xml.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/xml.tests.ps1 index 119d30a01c..7c402aea6f 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/xml.tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/xml.tests.ps1 @@ -1,68 +1,68 @@ -Describe "XML cmdlets" -Tags "Feature" { - Context "Select-XML" { - BeforeAll { - $fileName = New-Item -Path 'TestDrive:\testSelectXml.xml' - Push-Location "$fileName\.." - "" | out-file -LiteralPath $fileName - " " | out-file -LiteralPath $fileName -Append - "" | out-file -LiteralPath $fileName -Append - - $fileNameWithDots = $fileName.FullName.Replace("\", "\.\") - - $driveLetter = [string]($fileName.FullName)[0] - $fileNameAsNetworkPath = "\\localhost\$driveLetter`$" + $fileName.FullName.SubString(2) - - class TestData - { - [string] $testName - [hashtable] $parameters - - TestData($name, $parameters) - { - $this.testName = $name - $this.parameters = $parameters - } - } - - $testcases = @() - $testcases += [TestData]::new('literalpath with relative paths', @{LiteralPath = $fileName.Name; XPath = 'Root'}) - $testcases += [TestData]::new('literalpath with absolute paths', @{LiteralPath = $fileName.FullName; XPath = 'Root'}) - $testcases += [TestData]::new('literalpath with path with dots', @{LiteralPath = $fileNameWithDots; XPath = 'Root'}) - if ( ! $IsCore ) { - $testcases += [TestData]::new('literalpath with network path', @{LiteralPath = $fileNameAsNetworkPath; XPath = 'Root'}) - } - $testcases += [TestData]::new('path with relative paths', @{Path = $fileName.Name; XPath = 'Root'}) - $testcases += [TestData]::new('path with absolute paths', @{Path = $fileName.FullName; XPath = 'Root'}) - $testcases += [TestData]::new('path with path with dots', @{Path = $fileNameWithDots; XPath = 'Root'}) - if ( ! $IsCore ) { - $testcases += [TestData]::new('path with network path', @{Path = $fileNameAsNetworkPath; XPath = 'Root'}) - } - } - - AfterAll { - Remove-Item -LiteralPath $fileName -Force -ErrorAction SilentlyContinue - Pop-Location - } - - $testcases | % { - - $params = $_.parameters - - It $_.testName { - @(Select-XML @params).Count | Should Be 1 - } - } - - It "literalpath with non filesystem path" { - $__data = "abcdefg" - Select-XML -literalPath variable:__data "Root" -ErrorVariable selectXmlError -ErrorAction SilentlyContinue - $selectXmlError.FullyQualifiedErrorId | Should Be 'ProcessingFile,Microsoft.PowerShell.Commands.SelectXmlCommand' - } - - It "path with non filesystem path" { - $__data = "abcdefg" - Select-XML -Path variable:\__data "Root" -ErrorVariable selectXmlError -ErrorAction SilentlyContinue - $selectXmlError.FullyQualifiedErrorId | Should Be 'ProcessingFile,Microsoft.PowerShell.Commands.SelectXmlCommand' - } - } -} +Describe "XML cmdlets" -Tags "Feature" { + Context "Select-XML" { + BeforeAll { + $fileName = New-Item -Path 'TestDrive:\testSelectXml.xml' + Push-Location "$fileName\.." + "" | out-file -LiteralPath $fileName + " " | out-file -LiteralPath $fileName -Append + "" | out-file -LiteralPath $fileName -Append + + $fileNameWithDots = $fileName.FullName.Replace("\", "\.\") + + $driveLetter = [string]($fileName.FullName)[0] + $fileNameAsNetworkPath = "\\localhost\$driveLetter`$" + $fileName.FullName.SubString(2) + + class TestData + { + [string] $testName + [hashtable] $parameters + + TestData($name, $parameters) + { + $this.testName = $name + $this.parameters = $parameters + } + } + + $testcases = @() + $testcases += [TestData]::new('literalpath with relative paths', @{LiteralPath = $fileName.Name; XPath = 'Root'}) + $testcases += [TestData]::new('literalpath with absolute paths', @{LiteralPath = $fileName.FullName; XPath = 'Root'}) + $testcases += [TestData]::new('literalpath with path with dots', @{LiteralPath = $fileNameWithDots; XPath = 'Root'}) + if ( ! $IsCore ) { + $testcases += [TestData]::new('literalpath with network path', @{LiteralPath = $fileNameAsNetworkPath; XPath = 'Root'}) + } + $testcases += [TestData]::new('path with relative paths', @{Path = $fileName.Name; XPath = 'Root'}) + $testcases += [TestData]::new('path with absolute paths', @{Path = $fileName.FullName; XPath = 'Root'}) + $testcases += [TestData]::new('path with path with dots', @{Path = $fileNameWithDots; XPath = 'Root'}) + if ( ! $IsCore ) { + $testcases += [TestData]::new('path with network path', @{Path = $fileNameAsNetworkPath; XPath = 'Root'}) + } + } + + AfterAll { + Remove-Item -LiteralPath $fileName -Force -ErrorAction SilentlyContinue + Pop-Location + } + + $testcases | % { + + $params = $_.parameters + + It $_.testName { + @(Select-XML @params).Count | Should Be 1 + } + } + + It "literalpath with non filesystem path" { + $__data = "abcdefg" + Select-XML -literalPath variable:__data "Root" -ErrorVariable selectXmlError -ErrorAction SilentlyContinue + $selectXmlError.FullyQualifiedErrorId | Should Be 'ProcessingFile,Microsoft.PowerShell.Commands.SelectXmlCommand' + } + + It "path with non filesystem path" { + $__data = "abcdefg" + Select-XML -Path variable:\__data "Root" -ErrorVariable selectXmlError -ErrorAction SilentlyContinue + $selectXmlError.FullyQualifiedErrorId | Should Be 'ProcessingFile,Microsoft.PowerShell.Commands.SelectXmlCommand' + } + } +}